Паттерн "Адаптер" в Angular
Паттерн Адаптер (Adapter Pattern) — это структурный паттерн проектирования, который позволяет объектам с несовместимыми интерфейсами работать вместе. Адаптер выступает в роли посредника, который преобразует интерфейс одного класса в интерфейс, ожидаемый клиентом.
Основные концепции
- Целевой интерфейс (Target): Интерфейс, который ожидает клиент.
- Клиент (Client): Объект, который использует целевой интерфейс.
- Адаптируемый (Adaptee): Класс с несовместимым интерфейсом, который нужно адаптировать.
- Адаптер (Adapter): Класс, который преобразует интерфейс адаптируемого класса в целевой интерфейс.
Пример использования
Предположим, у нас есть старая библиотека для работы с аутентификацией, но интерфейс этой библиотеки не соответствует тому, что требуется нашему Angular приложению. Мы хотим использовать паттерн Адаптер, чтобы интегрировать эту библиотеку в наше приложение.
Шаги
- Создадим целевой интерфейс (Target)
- Адаптируемый класс (Adaptee)
- Адаптер (Adapter)
- .Используем Адаптер в Angular компоненте (Client)
1. Целевой интерфейс (Target)
Целевой интерфейс описывает методы, которые должны быть реализованы для работы с аутентификацией.
// auth.service.ts
export interface AuthService {
login(username: string, password: string): Promise<boolean>;
logout(): void;
isAuthenticated(): boolean;
}
2. Адаптируемый класс (Adaptee)
Адаптируемый класс представляет собой старую библиотеку, которую нужно адаптировать.
// legacy-auth.ts
export class LegacyAuth {
signIn(user: string, pass: string): boolean {
console.log('Using legacy auth system to sign in...');
return user === 'admin' && pass === 'admin'; // Simplified example
}
signOut(): void {
console.log('Using legacy auth system to sign out...');
}
checkAuth(): boolean {
console.log('Using legacy auth system to check authentication...');
return true; // Simplified example
}
}
3. Адаптер (Adapter)
Адаптер реализует целевой интерфейс и использует адаптируемый класс для выполнения работы.
// auth-adapter.service.ts
import { Injectable } from '@angular/core';
import { AuthService } from './auth.service';
import { LegacyAuth } from './legacy-auth';
@Injectable({
providedIn: 'root'
})
export class AuthAdapterService implements AuthService {
private legacyAuth: LegacyAuth;
constructor() {
this.legacyAuth = new LegacyAuth();
}
async login(username: string, password: string): Promise<boolean> {
return new Promise((resolve) => {
const result = this.legacyAuth.signIn(username, password);
resolve(result);
});
}
logout(): void {
this.legacyAuth.signOut();
}
isAuthenticated(): boolean {
return this.legacyAuth.checkAuth();
}
}
Использование адаптера в Angular компоненте (Client)
Теперь мы можем использовать наш адаптер в Angular компоненте для работы с аутентификацией.
// app.component.ts
import { Component } from '@angular/core';
import { AuthService } from './auth.service';
import { AuthAdapterService } from './auth-adapter.service';
@Component({
selector: 'app-root',
template: `
<div>
<button (click)="login()">Login</button>
<button (click)="logout()">Logout</button>
<p *ngIf="isAuthenticated()">Authenticated</p>
<p *ngIf="!isAuthenticated()">Not Authenticated</p>
</div>
`
})
export class AppComponent {
constructor(private authService: AuthAdapterService) { }
async login() {
const success = await this.authService.login('admin', 'admin');
if (success) {
console.log('Login successful');
} else {
console.log('Login failed');
}
}
logout() {
this.authService.logout();
console.log('Logged out');
}
isAuthenticated(): boolean {
return this.authService.isAuthenticated();
}
}
Пояснение
- Целевой интерфейс (AuthService) описывает методы, необходимые для работы с аутентификацией.
- Адаптируемый класс (LegacyAuth) представляет собой старую библиотеку с несовместимым интерфейсом.
- Адаптер (AuthAdapterService) реализует целевой интерфейс и использует методы старой библиотеки для выполнения задач аутентификации.
- Клиент (AppComponent) использует адаптер для работы с аутентификацией, не зная о существовании старой библиотеки.