Паттерн "Абстрактная фабрика"
Паттерн "Абстрактная фабрика" (Abstract Factory) предоставляет интерфейс для создания семейств взаимосвязанных или взаимозависимых объектов, не специфицируя их конкретные классы. Этот паттерн полезен, когда система должна быть независимой от процесса создания, компоновки и представления продуктов.
Рассмотрим пример, где мы используем паттерн "Абстрактная фабрика" для создания различных UI компонентов для различных тем оформления (например, светлая и темная тема) в Angular.
Шаг 1: Создание интерфейсов продуктов
Создадим интерфейсы для наших продуктов: кнопок и чекбоксов.
// button.interface.ts export interface Button { render(): void; } // checkbox.interface.ts export interface Checkbox { render(): void; }
Шаг 2: Создание конкретных продуктов
Реализуем конкретные продукты для светлой и темной тем.
// light-button.ts import { Button } from './button.interface'; export class LightButton implements Button { render(): void { console.log('Rendering a light-themed button.'); } } // dark-button.ts import { Button } from './button.interface'; export class DarkButton implements Button { render(): void { console.log('Rendering a dark-themed button.'); } } // light-checkbox.ts import { Checkbox } from './checkbox.interface'; export class LightCheckbox implements Checkbox { render(): void { console.log('Rendering a light-themed checkbox.'); } } // dark-checkbox.ts import { Checkbox } from './checkbox.interface'; export class DarkCheckbox implements Checkbox { render(): void { console.log('Rendering a dark-themed checkbox.'); } }
Шаг 3: Создание интерфейса фабрики
Создадим интерфейс фабрики для создания кнопок и чекбоксов.
// ui-factory.interface.ts import { Button } from './button.interface'; import { Checkbox } from './checkbox.interface'; export interface UIFactory { createButton(): Button; createCheckbox(): Checkbox; }
Шаг 4: Создание конкретных фабрик
Реализуем конкретные фабрики для светлой и темной тем.
// light-ui-factory.ts import { UIFactory } from './ui-factory.interface'; import { Button } from './button.interface'; import { Checkbox } from './checkbox.interface'; import { LightButton } from './light-button'; import { LightCheckbox } from './light-checkbox'; export class LightUIFactory implements UIFactory { createButton(): Button { return new LightButton(); } createCheckbox(): Checkbox { return new LightCheckbox(); } } // dark-ui-factory.ts import { UIFactory } from './ui-factory.interface'; import { Button } from './button.interface'; import { Checkbox } from './checkbox.interface'; import { DarkButton } from './dark-button'; import { DarkCheckbox } from './dark-checkbox'; export class DarkUIFactory implements UIFactory { createButton(): Button { return new DarkButton(); } createCheckbox(): Checkbox { return new DarkCheckbox(); } }
Шаг 5: Использование абстрактной фабрики в Angular компоненте
Создадим Angular компонент, который использует абстрактную фабрику для создания UI компонентов в зависимости от выбранной темы.
// app.component.ts import { Component, OnInit } from '@angular/core'; import { UIFactory } from './ui-factory.interface'; import { LightUIFactory } from './light-ui-factory'; import { DarkUIFactory } from './dark-ui-factory'; import { Button } from './button.interface'; import { Checkbox } from './checkbox.interface'; @Component({ selector: 'app-root', template: ` <button (click)="setTheme('light')">Light Theme</button> <button (click)="setTheme('dark')">Dark Theme</button> <button (click)="renderUI()">Render UI</button> `, }) export class AppComponent implements OnInit { private factory: UIFactory; private button: Button; private checkbox: Checkbox; ngOnInit(): void { this.setTheme('light'); // Default theme } setTheme(theme: string): void { if (theme === 'light') { this.factory = new LightUIFactory(); } else if (theme === 'dark') { this.factory = new DarkUIFactory(); } this.createUIComponents(); } createUIComponents(): void { this.button = this.factory.createButton(); this.checkbox = this.factory.createCheckbox(); } renderUI(): void { this.button.render(); this.checkbox.render(); } }