跳至主要內容

外观模式

约 521 字

外观模式

核心思想

外观模式提供了一个统一的接口来访问子系统中的一组接口。

典型用例

整合微服务接口

在微服务架构中,外观模式可以用来提供一个统一的接口来整合多个微服务,使得客户端不需要与每个服务单独交互。

在这个例子中,外观服务类提供了一个统一的接口来访问多个微服务接口。客户端代码通过与外观类来交互,而不是直接与每个微服务交互。

// npm run code src/code/design-pattern/facade/unify-microservices.ts

export {};

// 假设有几个微服务,每个服务都有自己的接口

// 用户服务
class UserService {
    getUser(userId: string): string {
        return `User info for ${userId}`;
    }
}

// 订单服务
class OrderService {
    getOrder(orderId: string): string {
        return `Order details for ${orderId}`;
    }
}

// 支付服务
class PaymentService {
    processPayment(amount: number): string {
        return `Processed payment of $${amount}`;
    }
}

// 创建一个外观类来封装对微服务的访问
class ServicesFacade {
    private userService: UserService;
    private orderService: OrderService;
    private paymentService: PaymentService;

    constructor() {
        this.userService = new UserService();
        this.orderService = new OrderService();
        this.paymentService = new PaymentService();
    }

    getUserInfo(userId: string): string {
        return this.userService.getUser(userId);
    }

    getOrderDetails(orderId: string): string {
        return this.orderService.getOrder(orderId);
    }

    makePayment(amount: number): string {
        return this.paymentService.processPayment(amount);
    }
}


const servicesFacade = new ServicesFacade();

// 客户端现在可以通过外观接口来访问服务,而无需直接与每个服务交互
console.log(servicesFacade.getUserInfo("user123"));
console.log(servicesFacade.getOrderDetails("order456"));
console.log(servicesFacade.makePayment(100));

简化复杂子系统的访问

当子系统变得复杂或者当需要简化子系统的一组接口时,外观模式可以用于提供一个简单的接口给外部客户端。这在涉及到复杂库、框架或API集合的情况下尤其有用。

// npm run code src/code/design-pattern/facade/simplify-access-to-complex-subsystems.ts

export {};

// 定义复杂子系统的类
class SystemA {
    operationA(): string {
        return 'SystemA operation';
    }
}

class SystemB {
    operationB(): string {
        return 'SystemB operation';
    }
}

class SystemC {
    operationC(): string {
        return 'SystemC operation';
    }
}

// 创建外观类
class Facade {
    private systemA: SystemA;
    private systemB: SystemB;
    private systemC: SystemC;

    constructor() {
        this.systemA = new SystemA();
        this.systemB = new SystemB();
        this.systemC = new SystemC();
    }

    // 提供给外部的简化接口
    operate(): string {
        const resultA = this.systemA.operationA();
        const resultB = this.systemB.operationB();
        const resultC = this.systemC.operationC();

        // 组合子系统的操作
        return `${resultA} | ${resultB} | ${resultC}`;
    }
}

// 客户端代码
const facade = new Facade();
console.log(facade.operate());

封装客户端和子系统的交互

在需要将客户端与子系统的直接交互隔离开时,外观可以作为一个中间层来保护子系统不受客户端的影响,同时也简化客户端对子系统的使用。

// npm run code src/code/design-pattern/facade/encapsulate-client-and-subsystem-interactions.ts

export {};

// 子系统类
class SubsystemOne {
    operationOne(): string {
        return 'SubsystemOne: Ready!';
    }

    operationN(): string {
        return 'SubsystemOne: Go!';
    }
}

class SubsystemTwo {
    operationOne(): string {
        return 'SubsystemTwo: Get ready!';
    }

    operationZ(): string {
        return 'SubsystemTwo: Fire!';
    }
}

// 外观类
class Facade {
    private subsystemOne: SubsystemOne;
    private subsystemTwo: SubsystemTwo;

    constructor(subsystemOne: SubsystemOne, subsystemTwo: SubsystemTwo) {
        this.subsystemOne = subsystemOne || new SubsystemOne();
        this.subsystemTwo = subsystemTwo || new SubsystemTwo();
    }

    // 外观类提供的简化接口
    operation(): string {
        let result = 'Facade initializes subsystems:\n';
        result += this.subsystemOne.operationOne();
        result += this.subsystemTwo.operationOne();
        result += 'Facade orders subsystems to perform the action:\n';
        result += this.subsystemOne.operationN();
        result += this.subsystemTwo.operationZ();
        return result;
    }
}

// 客户端代码
const subsystemOne = new SubsystemOne();
const subsystemTwo = new SubsystemTwo();
const facade = new Facade(subsystemOne, subsystemTwo);

// 客户端通过外观类与子系统交互
console.log(facade.operation());

提供子系统的抽象层

当子系统的实现和客户端代码可能经常变化时,外观模式可以用来为子系统提供一个稳定的接口,隔离了子系统的实现细节和客户端的直接交互,从而减少系统的耦合度。

// npm run code src/code/design-pattern/facade/provides-abstraction-layer-for-subsystem.ts

export {};

// 子系统类
class SubsystemOne {
    complexOperationOne(): string {
        return 'SubsystemOne: Complex operation';
    }
}

class SubsystemTwo {
    complexOperationTwo(): string {
        return 'SubsystemTwo: Complex operation';
    }
}

// 外观类
class Facade {
    private subsystemOne: SubsystemOne;
    private subsystemTwo: SubsystemTwo;

    constructor(subsystemOne: SubsystemOne, subsystemTwo: SubsystemTwo) {
        this.subsystemOne = subsystemOne || new SubsystemOne();
        this.subsystemTwo = subsystemTwo || new SubsystemTwo();
    }

    // 外观类提供的稳定接口
    operation(): string {
        const resultOne = this.subsystemOne.complexOperationOne();
        const resultTwo = this.subsystemTwo.complexOperationTwo();

        return `Facade coordinates operations: \n${resultOne}\n${resultTwo}`;
    }
}

// 客户端代码
const facade = new Facade(new SubsystemOne(), new SubsystemTwo());
console.log(facade.operation());

分层结构中的接口

在多层架构的应用程序中,外观模式可以用于定义系统中每一层的入口点,使得层与层之间的通信更加清晰和有序。

// npm run code src/code/design-pattern/facade/interfaces-in-hierarchical-structure.ts

export {};

// 数据访问层(DAL)
class DataAccessLayer {
    fetchData(): string {
        return 'Data fetched from database';
    }
}

// 业务逻辑层(BLL)
class BusinessLogicLayer {
    private dal: DataAccessLayer;

    constructor(dal: DataAccessLayer) {
        this.dal = dal;
    }

    processData(): string {
        const data = this.dal.fetchData();
        return `Processed ${data}`;
    }
}

// 表示层(UI)
class PresentationLayer {
    private bll: BusinessLogicFacade; // 使用 BusinessLogicFacade

    constructor(bll: BusinessLogicFacade) {
        this.bll = bll;
    }

    displayData(): void {
        const processedData = this.bll.processData();
        console.log(`Displaying ${processedData}`);
    }
}

// 外观类为每一层
class DataAccessFacade {
    private dal: DataAccessLayer;

    constructor() {
        this.dal = new DataAccessLayer();
    }

    fetchData(): string {
        return this.dal.fetchData();
    }
}

class BusinessLogicFacade {
    private bll: BusinessLogicLayer;

    constructor(dalFacade: DataAccessFacade) {
        const dal = dalFacade; // 使用 DataAccessFacade
        this.bll = new BusinessLogicLayer(dal);
    }

    processData(): string {
        return this.bll.processData();
    }
}

class PresentationFacade {
    private pl: PresentationLayer;

    constructor(bllFacade: BusinessLogicFacade) {
        this.pl = new PresentationLayer(bllFacade);
    }

    displayData(): void {
        this.pl.displayData();
    }
}

// 客户端代码
const dalFacade = new DataAccessFacade();
const bllFacade = new BusinessLogicFacade(dalFacade);
const presentationFacade = new PresentationFacade(bllFacade);

presentationFacade.displayData();

上次编辑于: