跳转到主要内容

来源:Angular中的设计模式

欲了解更多问题和答案,请访问我们的网站“前端面试问题”

Angular是一种流行的用于构建web应用程序的JavaScript框架,在Angular中,通常使用几种设计模式来构建和组织代码。这些设计模式帮助开发人员创建可维护、可扩展和模块化的应用程序。

以下是Angular中经常使用的一些设计模式:

1.Singleton模式:

角度服务通常使用Singleton模型来实现。一个服务被实例化一次,并在多个组件之间共享,从而允许它们进行通信和共享数据。

要在Angular中实现Singleton模式,可以执行以下步骤:

a.使用Angular CLI创建服务:

ng generate service MySingletonService

b.有两种方法可以在angular中创建单个服务,即使用

-> providedIn property

-> NgModule providers arrays

c.打开生成的服务文件(`my singleton service.service.ts`),按如下方式进行修改:

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class MySingletonService {
  // Your service implementation goes here
}

d.“@Injectable”装饰器中的“providedIn:”root“”属性是在Angular中实现Singleton模式的关键。这条消息告诉Angular在根级别提供服务,使其可以在整个应用程序中访问。

e.您现在可以在组件中使用“MySingletonService”,方法是将其注入其构造函数:


import { Component } from '@angular/core';
import { MySingletonService } from './my-singleton-service.service';

@Component({
  selector: 'app-my-component',
  template: '...',
})
export class MyComponent {
  constructor(private mySingletonService: MySingletonService) {
    // Access the shared service instance here
  }
}

通过将“MySingletonService”注入多个组件,您将在整个应用程序中访问服务的同一实例,从而确保数据的一致性和共享性。

需要注意的是,Angular本身管理着单例服务的生命周期。它创建并维护服务的单个实例,并在请求它的组件之间共享它。

在NgModule提供者数组的情况下,通过将服务作为值传递给提供者数组来创建单例服务,如果NgModule是根应用程序模块,则该服务将作为单例服务在整个应用程序中可用。

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { MySingletonService } from './my-singleton-service.service';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule],
  providers: [MySingletonService], // Add the service here
  bootstrap: [AppComponent]
})
export class AppModule { }

这就是使用服务在Angular中实现Singleton模式的方法。这允许您在整个应用程序中共享数据、维护状态并提供集中的功能。

2.依赖注入(DI)模式:

Angular利用DI模式来管理组件和服务之间的依赖关系。使用DI,通过构造函数注入或属性注入将所需的依赖关系提供给组件或服务,从而促进松耦合和可测试性。

// Component using DI
constructor(private productService: ProductService) {
  // Use the productService
}

3.观察者模式:

Angular通过EventEmitter类和RxJS库利用观察者模式。组件可以使用EventEmitters发出事件,其他组件可以订阅这些事件以做出相应的反应。

// Component emitting an event
@Output() productSelected = new EventEmitter();

selectProduct(product: Product) {
  this.productSelected.emit(product);
}

// Component subscribing to an event

//订阅事件的组件

4.策略模式:

策略模式使您能够在运行时根据特定条件或要求动态选择不同的策略并在它们之间切换。通过将这些行为封装在单独的类中,组件可以根据特定条件在策略之间切换。

以下是在Angular中实现Strategy模式的示例:

a.定义一个接口,表示策略的常见行为。假设我们有一个支付处理场景:

// payment-strategy.interface.ts
export interface PaymentStrategy {
  processPayment(amount: number): void;
}

b.通过创建实现“PaymentStrategy”接口的独立类来实现多种策略。每个类都将提供自己的“processPayment”方法实现:

// credit-card-strategy.ts
export class CreditCardStrategy implements PaymentStrategy {
  processPayment(amount: number): void {
    console.log(`Processing credit card payment of $${amount}`);
    // Perform credit card payment processing logic here
  }
}

// paypal-strategy.ts
export class PaypalStrategy implements PaymentStrategy {
  processPayment(amount: number): void {
    console.log(`Processing PayPal payment of $${amount}`);
    // Perform PayPal payment processing logic here
  }
}

c.创建一个将使用策略的上下文类,并提供一种设置主动策略的方法:

// payment-context.ts
import { PaymentStrategy } from './payment-strategy.interface';

export class PaymentContext {
  private strategy: PaymentStrategy;

  setStrategy(strategy: PaymentStrategy): void {
    this.strategy = strategy;
  }

  processPayment(amount: number): void {
    this.strategy.processPayment(amount);
  }
}

d.现在,您可以在Angular组件或服务中使用这些策略。例如

import { Component } from '@angular/core';
import { PaymentContext } from './payment-context';
import { CreditCardStrategy } from './credit-card-strategy';
import { PaypalStrategy } from './paypal-strategy';

@Component({
  selector: 'app-payment-component',
  template: '...',
})
export class PaymentComponent {
  constructor(private paymentContext: PaymentContext) {}

  processCreditCardPayment(amount: number): void {
    this.paymentContext.setStrategy(new CreditCardStrategy());
    this.paymentContext.processPayment(amount);
  }

  processPaypalPayment(amount: number): void {
    this.paymentContext.setStrategy(new PaypalStrategy());
    this.paymentContext.processPayment(amount);
  }
}

e.在本例中,“PaymentComponent”使用“PaymentContext”根据用户操作或条件在不同的支付策略(“CreditCardStrategy”和“PaypalStrategy”)之间切换。通过“setStrategy”设置活动策略,您可以动态更改“processPayment”中支付处理逻辑的行为。

此实现允许轻松扩展,因为您可以通过实现“PaymentStrategy”接口添加新策略,并在“PaymentComponent”或任何其他需要支付处理功能的组件中可互换使用它们。

策略模式通过将不同算法或行为的实现与客户端代码分离,提供灵活性和可维护性,允许您在不修改现有代码的情况下更改或扩展策略。

5.装饰器模式:

角度装饰器,如@Component和@Injectable,是基于装饰器模式的。decorator提供了一种增强或修改类或类成员行为的方法,而无需直接修改底层代码。

a.创建一个代表核心功能的基本组件:

import { Component } from '@angular/core';

@Component({
  selector: 'app-base-component',
  template: 'Base Component',
})
export class BaseComponent {}

b.创建一个装饰器组件来扩展基本组件:

import { Component, ViewChild } from '@angular/core';
import { BaseComponent } from './base-component';

@Component({
  selector: 'app-decorator',
  template: `
    <div>
      <p>This is the decorator component</p>
      <ng-content></ng-content>
    </div>
  `,
})
export class DecoratorComponent extends BaseComponent {}

 

在本例中,“DecoratorComponent”是扩展“BaseComponent”功能的子组件。它将“BaseComponent”包装在自己内部,并使用“<ng content>”添加额外内容。这允许您围绕基本组件注入额外的行为或模板内容。

c.在应用程序中使用decorator组件:

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `
    <app-decorator>
      <app-base-component></app-base-component>
    </app-decorator>
  `,
})
export class AppComponent {}

在“AppComponent”模板中,“BaseComponent”使用其选择器“<app decorator>”包装在“DecoratorComponent”中。您可以在“DecoratorComponent”中注入其他组件、模板或HTML内容,以扩展或修改“BaseComponent”的行为。

通过在Angular中使用Decorator模式,可以通过将现有组件封装在Decorator组件中来动态扩展或修改现有组件的功能。这种方法提供了灵活性、代码可重用性和可维护性,因为您可以在根据需要添加特定行为或内容的同时重用基本组件。

6.立面模式:

立面模式是一种结构设计模式,它为复杂的子系统提供了简化的界面,使其更易于使用和理解。在Angular中,您可以应用Facade模式来创建一个简化的API或服务,该API或服务封装了与多个组件、服务或模块交互的复杂性。

以下是在Angular中实现Facade模式的示例:

a.确定要简化以供客户端使用的复杂子系统或相关组件/服务集。

b.创建一个封装与复杂子系统交互的Facade服务。Facade服务将为客户端提供一个简化的接口,以访问子系统的功能。

import { Injectable } from '@angular/core';
import { ComplexServiceA } from './complex-service-a';
import { ComplexServiceB } from './complex-service-b';

@Injectable()
export class FacadeService {
  constructor(private serviceA: ComplexServiceA, private serviceB: ComplexServiceB) {}

  // Provide simplified methods that internally call the appropriate complex subsystem methods
  performOperation(): void {
    this.serviceA.complexOperationA();
    this.serviceB.complexOperationB();
  }
}

c.实现Facade服务与之交互的复杂子系统组件/服务。这些组件/服务处理实际的复杂逻辑。


@Injectable()
export class ComplexServiceA {
  complexOperationA(): void {
    // Complex logic of service A
    console.log('Performing complex operation A');
  }
}

@Injectable()
export class ComplexServiceB {
  complexOperationB(): void {
    // Complex logic of service B
    console.log('Performing complex operation B');
  }
}

d.在组件中使用Facade服务来简化复杂子系统的使用:

import { Component } from '@angular/core';
import { FacadeService } from './facade.service';

@Component({
  selector: 'app-client-component',
  template: '...',
})
export class ClientComponent {
  constructor(private facadeService: FacadeService) {}

  performFacadeOperation(): void {
    this.facadeService.performOperation();
  }
}

e.在这个例子中,“ClientComponent”利用“FacadeService”来执行复杂的操作,而不需要直接与复杂的子系统(“ComplexServiceA”和“ComplexService B”)交互。“FacadeService”封装了复杂性,并为客户端组件提供了一个简化的交互接口。

通过在Angular中使用Facade模式,您可以简化复杂子系统的使用,隐藏其实现细节,并为客户端提供一个简单易用的界面。这通过抽象在单个门面后面与多个组件或服务交互的复杂性来提高代码的可维护性、可读性和模块性。

7.复合模式:

复合设计模式是一种结构设计模式,用于将对象组合成树状结构。组件可以由其他组件组成,形成树状结构。此模式允许创建可重用的分层UI组件。

在Angular中,可以应用Composite模式来表示组件或服务之间的层次关系。

以下是在Angular中实现Composite模式的示例:

a.创建一个抽象类或接口,表示单个对象和组的共同行为:

// component.interface.ts
export interface ComponentInterface {
  operation(): void;
}

b.为单个对象实现抽象类或接口:

// leaf.component.ts
import { ComponentInterface } from './component.interface';

export class LeafComponent implements ComponentInterface {
  operation(): void {
    console.log('Performing operation on a leaf component.');
  }
}

c.实现复合对象的抽象类或接口,既可以包含单个对象,也可以包含其他复合对象:

// composite.component.ts
import { ComponentInterface } from './component.interface';

export class CompositeComponent implements ComponentInterface {
  private children: Component[] = [];

  add(component: ComponentInterface): void {
    this.children.push(component);
  }

  remove(component: ComponentInterface): void {
    const index = this.children.indexOf(component);
    if (index > -1) {
      this.children.splice(index, 1);
    }
  }

  operation(): void {
    console.log('Performing operation on the composite component.');
    for (const child of this.children) {
      child.operation();
    }
  }
}

d.使用复合对象创建组件的树状结构:


import { ComponentInterface } from './component.interface';
import { LeafComponent } from './leaf.component';
import { CompositeComponent } from './composite.component';

// Create leaf components
const leaf1: ComponentInterface = new LeafComponent();
const leaf2: ComponentInterface = new LeafComponent();

// Create composite component
const composite: ComponentInterface = new CompositeComponent();
composite.add(leaf1);
composite.add(leaf2);

// Create another composite component
const composite2: ComponentInterface = new CompositeComponent();
composite2.add(composite);
composite2.add(leaf1);

// Perform operation on the composite structure
composite2.operation();

e.在这个例子中,我们使用Composite模式创建了一个树状结构。“CompositeComponent”可以包含单个“LeafComponent”对象和其他“CompositeComponent'对象。在顶级“CompositeComponent”上调用“operation()”方法将递归调用其所有子级上的操作,无论它们是叶组件还是其他复合组件。

通过在Angular中使用Composite模式,可以以统一的方式表示组件或服务之间的复杂层次关系。它允许您以一致的方式处理单个对象和对象组,简化代码并启用对复合结构的递归操作。

8.工厂模式:

工厂模式是一种创造性的设计模式,它提供了一个创建对象的接口,而不指定将要创建的对象的确切类。在Angular中,您可以应用Factory模式来封装对象创建逻辑,并为创建不同类的实例提供一个集中的位置。

以下是在Angular中实现Factory模式的示例:

a.定义一个抽象类或接口,表示要创建的对象的常见行为:

// product.interface.ts
export interface Product {
  operation(): void;
}

b.实现符合“产品”界面的多个类:

// product-a.ts
export class ProductA implements Product {
  operation(): void {
    console.log('Product A operation.');
  }
}

// product-b.ts
export class ProductB implements Product {
  operation(): void {
    console.log('Product B operation.');
  }
}

c.创建一个封装对象创建逻辑的工厂类:

// product-factory.ts
import { Product } from './product.interface';
import { ProductA } from './product-a';
import { ProductB } from './product-b';

export class ProductFactory {
  createProduct(type: string): Product {
    if (type === 'A') {
      return new ProductA();
    } else if (type === 'B') {
      return new ProductB();
    }

    throw new Error('Invalid product type');
  }
}

d.使用工厂类创建所需产品的实例:

import { Component } from '@angular/core';
import { ProductFactory } from './product-factory';
import { Product } from './product.interface';

@Component({
  selector: 'app-example',
  template: '...',
})
export class ExampleComponent {
  constructor(private productFactory: ProductFactory) {}

  createProduct(type: string): void {
    const product: Product = this.productFactory.createProduct(type);
    product.operation();
  }
}

e.在本例中,“ExampleComponent”使用“ProductFactory”根据提供的类型创建不同产品的实例。通过调用所需类型(“A”或“B”)的“createProduct”方法,它将接收相应产品类的实例,并可以调用其“operation()”方法。

在Angular中使用Factory模式为创建对象提供了一个集中的位置,并将客户端代码与具体类解耦。它允许灵活的对象创建,并通过添加新的产品类和相应地更新工厂逻辑来实现简单的可扩展性。

这些是Angular中常用的一些设计模式。然而,值得注意的是,Angular本身遵循MVC(模型-视图-控制器)体系结构模式,其中组件充当控制器,模板代表视图,服务充当模型。

文章链接