angular
July 8

Паттерн "Шаблонный метод"

Паттерн "Шаблонный метод" (Template Method) определяет скелет алгоритма в методе, оставляя определение реализации некоторых шагов подклассам. Этот паттерн позволяет подклассам переопределять определенные шаги алгоритма без изменения структуры алгоритма.

Рассмотрим пример, где мы используем паттерн "Шаблонный метод" в Angular для обработки различных типов данных, например, для рендеринга различных форм.

Создание базового класса с шаблонным методом

Для начала создадим абстрактный класс FormRenderer, который будет содержать шаблонный метод render и шаги алгоритма, которые могут быть переопределены в подклассах.

// form-renderer.ts
export abstract class FormRenderer {
  render(): void {
    this.setup();
    this.renderHeader();
    this.renderForm();
    this.renderFooter();
    this.teardown();
  }

  protected setup(): void {
    console.log('Default setup');
  }

  protected teardown(): void {
    console.log('Default teardown');
  }

  protected abstract renderHeader(): void;
  protected abstract renderForm(): void;
  protected abstract renderFooter(): void;
}

Создание подклассов

Теперь создадим два подкласса: UserFormRenderer и ProductFormRenderer, которые будут предоставлять конкретные реализации для методов renderHeader, renderForm и renderFooter.

// user-form-renderer.ts
import { FormRenderer } from './form-renderer';

export class UserFormRenderer extends FormRenderer {
  protected renderHeader(): void {
    console.log('Rendering User Form Header');
  }

  protected renderForm(): void {
    console.log('Rendering User Form Fields');
  }

  protected renderFooter(): void {
    console.log('Rendering User Form Footer');
  }
}

// product-form-renderer.ts
import { FormRenderer } from './form-renderer';

export class ProductFormRenderer extends FormRenderer {
  protected renderHeader(): void {
    console.log('Rendering Product Form Header');
  }

  protected renderForm(): void {
    console.log('Rendering Product Form Fields');
  }

  protected renderFooter(): void {
    console.log('Rendering Product Form Footer');
  }
}

Использование

Теперь создадим Angular компонент, который будет использовать шаблонный метод для рендеринга различных форм.

// form.component.ts
import { Component, OnInit } from '@angular/core';
import { UserFormRenderer } from './user-form-renderer';
import { ProductFormRenderer } from './product-form-renderer';
import { FormRenderer } from './form-renderer';

@Component({
  selector: 'app-form',
  template: `
    <button (click)="renderUserForm()">Render User Form</button>
    <button (click)="renderProductForm()">Render Product Form</button>
  `
})
export class FormComponent implements OnInit {
  constructor() {}

  ngOnInit(): void {}

  renderUserForm(): void {
    const userFormRenderer: FormRenderer = new UserFormRenderer();
    userFormRenderer.render();
  }

  renderProductForm(): void {
    const productFormRenderer: FormRenderer = new ProductFormRenderer();
    productFormRenderer.render();
  }
}

Объяснение

  1. Абстрактный класс FormRenderer:
    • Определяет метод render, который является шаблонным методом и задает последовательность шагов.
    • Содержит абстрактные методы renderHeader, renderForm и renderFooter, которые должны быть реализованы в подклассах.
    • Включает методы setup и teardown, которые имеют базовую реализацию и могут быть переопределены в подклассах при необходимости.
  2. Конкретные классы UserFormRenderer и ProductFormRenderer:
    • Реализуют абстрактные методы для конкретного типа формы (пользовательской и продуктовой формы соответственно).
  3. Компонент FormComponent:
    • Содержит кнопки для рендеринга различных форм.
    • При нажатии на кнопку создается экземпляр конкретного рендера и вызывается метод render, который использует шаблонный метод для выполнения рендеринга формы.