iOS设计模式之外观模式

130 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第8天,点击查看活动详情

概述:

  • 本文主要介绍iOS设计模式中的外观模式,外观模式为子系统中一组不同的接口供统一的接口。外观定义了上层接口,通过降低复杂度可隐藏子系统间的通信及依存关系,让子系统更易于使用。

1. 什么事外观模式

举个例子,比如今天你不想开车,叫了出租车。只要出租车把你送到目的地,你不太在意车的牌子和型号,只要对出租车司机说一句“送我去某个地方”,之后出租车司机就开始执行一系列的命令。出租车司机抽象了车辆操作接口分离开来。出租车司机和你之间的接口只是一个简单的“送我去某个地方“命令。
当你通过电话给商店下达订单时, 接线员就是该商店的所有服务和部门的外观。 接线员为你提供了一个同购物系统、 支付网关和各种送货服务进行互动的简单语音接口
很多旧的面向对象应用程序中,可能有许多类分散于带有各种功能的系统中。要把这些类用于某个功能,需要知道全部细节才能在一组算法中使用它们。如果从逻辑上将其中一些类组合成一个简化的接口,可以让这些类更易于使用。为子系统中一组不同接口提供统一接口的一种方式称为外观模式

外观模式:为系统中的一组接口提供一个统一的接口。外观定义一个高层接口,让子系统更易于使用。

2. 什么时候使用外观模式

以下两种常见的情形下,可以考虑使用这一模式。

  • 子系统正逐渐变得复杂。应用模式的过程中演化出许多的类。可以使用外观这些子系统类提供一个简单的接口
  • 可以使用外观对子系统进行分层。每个子系统级别有个外观作为入口点,让他们通过其他外观进行通信,可以简化它们的依赖关系

3.代码展示

你可以创建一个封装所需功能并隐藏其他代码的外观类, 从而无需使全部代码直接与数十个框架类进行交互。 该结构还能将未来框架升级或更换所造成的影响最小化, 因为你只需修改程序中外观方法的实现即可

import XCTest

/// The Facade class provides a simple interface to the complex logic of one or
/// several subsystems. The Facade delegates the client requests to the
/// appropriate objects within the subsystem. The Facade is also responsible for
/// managing their lifecycle. All of this shields the client from the undesired
/// complexity of the subsystem.
class Facade {

    private var subsystem1: Subsystem1
    private var subsystem2: Subsystem2

    /// Depending on your application's needs, you can provide the Facade with
    /// existing subsystem objects or force the Facade to create them on its
    /// own.
    init(subsystem1: Subsystem1 = Subsystem1(),
         subsystem2: Subsystem2 = Subsystem2()) {
        self.subsystem1 = subsystem1
        self.subsystem2 = subsystem2
    }

    /// The Facade's methods are convenient shortcuts to the sophisticated
    /// functionality of the subsystems. However, clients get only to a fraction
    /// of a subsystem's capabilities.
    func operation() -> String {

        var result = "Facade initializes subsystems:"
        result += " " + subsystem1.operation1()
        result += " " + subsystem2.operation1()
        result += "\n" + "Facade orders subsystems to perform the action:\n"
        result += " " + subsystem1.operationN()
        result += " " + subsystem2.operationZ()
        return result
    }
}

/// The Subsystem can accept requests either from the facade or client directly.
/// In any case, to the Subsystem, the Facade is yet another client, and it's
/// not a part of the Subsystem.
class Subsystem1 {

    func operation1() -> String {
        return "Sybsystem1: Ready!\n"
    }

    // ...

    func operationN() -> String {
        return "Sybsystem1: Go!\n"
    }
}

/// Some facades can work with multiple subsystems at the same time.
class Subsystem2 {

    func operation1() -> String {
        return "Sybsystem2: Get ready!\n"
    }

    // ...

    func operationZ() -> String {
        return "Sybsystem2: Fire!\n"
    }
}

/// The client code works with complex subsystems through a simple interface
/// provided by the Facade. When a facade manages the lifecycle of the
/// subsystem, the client might not even know about the existence of the
/// subsystem. This approach lets you keep the complexity under control.
class Client {
    // ...
    static func clientCode(facade: Facade) {
        print(facade.operation())
    }
    // ...
}

/// Let's see how it all works together.
class FacadeConceptual: XCTestCase {

    func testFacadeConceptual() {

        /// The client code may have some of the subsystem's objects already
        /// created. In this case, it might be worthwhile to initialize the
        /// Facade with these objects instead of letting the Facade create new
        /// instances.

        let subsystem1 = Subsystem1()
        let subsystem2 = Subsystem2()
        let facade = Facade(subsystem1: subsystem1, subsystem2: subsystem2)
        Client.clientCode(facade: facade)
    }
}

执行结果:

Facade initializes subsystems: Sybsystem1: Ready!
Sybsystem2: Get ready!

Facade orders subsystems to perform the action:
Sybsystem1: Go!
Sybsystem2: Fire!

4.总结

对于一些复杂的流程我们通常需要抽取出成一个简单的接口,或者子类流程较为复杂,子类通过外观模式进行抽取,最后把所有子类抽取成一个新的专用外观。外观模式主要解决我们复杂的系统,你可以让自己的代码独立于复杂子系统。但是外观可能会成为与程序中所有类都耦合的上帝对象。上一个部分接口适配桥接外观模式主要是接口适配。它们主要针对用更简单的接口或用不同的接口适配各种接口