Паттерн "Адаптер" в 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) использует адаптер для работы с аутентификацией, не зная о существовании старой библиотеки.