DESIGN DESIGN
  • 架构
  • 设计模式
  • 重构
  • UML
GitHub (opens new window)
  • 架构
  • 设计模式
  • 重构
  • UML
GitHub (opens new window)
  • 架构

  • 设计模式

    • 设计模式概述
    • 设计模式之简单工厂模式
    • 设计模式之工厂方法模式
    • 设计模式之抽象工厂模式
    • 设计模式之建造者模式
    • 设计模式之原型模式
    • 设计模式之单例模式
    • 设计模式之适配器模式
    • 设计模式之桥接模式
    • 设计模式之组合模式
    • 设计模式之装饰模式
    • 设计模式之外观模式
      • 意图
      • 适用场景
      • 结构
        • 结构说明
        • 结构代码范式
      • 伪代码
      • 案例
      • 与其他模式的关系
      • 参考资料
    • 设计模式之享元模式
    • 设计模式之代理模式
    • 设计模式之模板方法模式
    • 设计模式之命令模式
    • 设计模式之迭代器模式
    • 设计模式之观察者模式
    • 设计模式之解释器模式
    • 设计模式之中介者模式
    • 设计模式之职责链模式
    • 设计模式之备忘录模式
    • 设计模式之策略模式
    • 设计模式之访问者模式
    • 设计模式之状态模式
    • 面向对象原则
  • 重构

  • DDD

  • UML

  • 设计
  • 设计模式
dunwu
2015-01-19
目录

设计模式之外观模式

# 设计模式之外观模式

# 意图

外观模式 (Facade) 是一种结构型设计模式, 为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

  • 外观模式为复杂子系统提供了一个简单接口,并不为子系统添加新的功能和行为。
  • 外观模式实现了子系统与客户之间的松耦合关系。
  • 外观模式没有封装子系统的类,只是提供了简单的接口。 如果应用需要,它并不限制客户使用子系统类。因此可以再系统易用性与通用性之间选择。
  • 外观模式注重的是简化接口,它更多的时候是从架构的层次去看整个系统,而并非单个类的层次。

# 适用场景

  • 如果你需要一个指向复杂子系统的直接接口, 且该接口的功能有限, 则可以使用外观模式。
  • 如果需要将子系统组织为多层结构, 可以使用外观。

# 结构

img

# 结构说明

  1. 外观 (Facade) 提供了一种访问特定子系统功能的便捷方式, 其了解如何重定向客户端请求, 知晓如何操作一切活动部件。

  2. 创建附加外观 (Additional Facade) 类可以避免多种不相关的功能污染单一外观, 使其变成又一个复杂结构。 客户端和其他外观都可使用附加外观。

  3. 复杂子系统 (Complex Subsystem) 由数十个不同对象构成。 如果要用这些对象完成有意义的工作, 你必须深入了解子系统的实现细节, 比如按照正确顺序初始化对象和为其提供正确格式的数据。

    子系统类不会意识到外观的存在, 它们在系统内运作并且相互之间可直接进行交互。

  4. 客户端 (Client) 使用外观代替对子系统对象的直接调用。

# 结构代码范式

Facade : 了解每个子系统类的功能,负责分发客户端的请求给各个子系统去处理。

class Class1 {
    public void op1() {
        System.out.println("方法1");
    }
}

class Class2 {
    public void op2() {
        System.out.println("方法2");
    }
}

class Class3 {
    public void op3() {
        System.out.println("方法3");
    }
}

Subsystem Classes : 实现子系统功能。在不感知 Facade 的情况下,处理 Facade 对象分配的工作,

class Facade {
    private Class1 one = new Class1();
    private Class2 two = new Class2();
    private Class3 three = new Class3();

    public void op1() {
        System.out.println("Facade op1()");
        one.op1();
    }

    public void op2() {
        System.out.println("Facade op2()");
        two.op2();
    }

    public void op3() {
        System.out.println("Facade op3()");
        three.op3();
    }

    public void Method() {
        System.out.println("Facade Method()");
        three.op3();
        two.op2();
        one.op1();
    }
}

【客户端】

public class FacadePattern {
    public static void main(String[] args) {
        Facade facade = new Facade();
        facade.Method();

        facade.op1();
    }
}

【输出】

Facade Method()
方法3
方法2
方法1
Facade op1()
方法1

# 伪代码

在本例中, 外观模式简化了客户端与复杂视频转换框架之间的交互。

img

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

// 这里有复杂第三方视频转换框架中的一些类。我们不知晓其中的代码,因此无法
// 对其进行简化。

class VideoFile
// ...

class OggCompressionCodec
// ...

class MPEG4CompressionCodec
// ...

class CodecFactory
// ...

class BitrateReader
// ...

class AudioMixer
// ...


// 为了将框架的复杂性隐藏在一个简单接口背后,我们创建了一个外观类。它是在
// 功能性和简洁性之间做出的权衡。
class VideoConverter is
    method convert(filename, format):File is
        file = new VideoFile(filename)
        sourceCodec = new CodecFactory.extract(file)
        if (format == "mp4")
            destinationCodec = new MPEG4CompressionCodec()
        else
            destinationCodec = new OggCompressionCodec()
        buffer = BitrateReader.read(filename, sourceCodec)
        result = BitrateReader.convert(buffer, destinationCodec)
        result = (new AudioMixer()).fix(result)
        return new File(result)

// 应用程序的类并不依赖于复杂框架中成千上万的类。同样,如果你决定更换框架,
// 那只需重写外观类即可。
class Application is
    method main() is
        convertor = new VideoConverter()
        mp4 = convertor.convert("funny-cats-video.ogg", "mp4")
        mp4.save()

# 案例

使用示例: 使用 Java 开发的程序中经常会使用外观模式。 它在与复杂程序库和 API 协作时特别有用。

下面是一些核心 Java 程序库中的外观示例:

  • javax.faces.context.FacesContext (opens new window) 在底层使用了 Life­Cycle (opens new window)、 View­Handler (opens new window) 和 Navigation­Handler (opens new window) 这几个类, 但绝大多数客户端不知道。
  • javax.faces.context.ExternalContext (opens new window) 在内部使用了 Servlet­Context (opens new window)、 Http­Session (opens new window)、 Http­Servlet­Request (opens new window)、 Http­Servlet­Response (opens new window) 和其他一些类。

识别方法: 外观可以通过使用简单接口, 但将绝大部分工作委派给其他类的类来识别。 通常情况下, 外观管理着其所使用的对象的完整生命周期。

# 与其他模式的关系

  • 外观模式 (opens new window)为现有对象定义了一个新接口, 适配器模式 (opens new window)则会试图运用已有的接口。 适配器通常只封装一个对象, 外观通常会作用于整个对象子系统上。
  • 当只需对客户端代码隐藏子系统创建对象的方式时, 你可以使用抽象工厂模式 (opens new window)来代替外观 (opens new window)。
  • 享元模式 (opens new window)展示了如何生成大量的小型对象, 外观 (opens new window)则展示了如何用一个对象来代表整个子系统。
  • 外观 (opens new window)和中介者模式 (opens new window)的职责类似: 它们都尝试在大量紧密耦合的类中组织起合作。
    • 外观为子系统中的所有对象定义了一个简单接口, 但是它不提供任何新功能。 子系统本身不会意识到外观的存在。 子系统中的对象可以直接进行交流。
    • 中介者将系统中组件的沟通行为中心化。 各组件只知道中介者对象, 无法直接相互交流。
  • 外观 (opens new window)类通常可以转换为单例模式 (opens new window)类, 因为在大部分情况下一个外观对象就足够了。
  • 外观 (opens new window)与代理模式 (opens new window)的相似之处在于它们都缓存了一个复杂实体并自行对其进行初始化。 代理与其服务对象遵循同一接口, 使得自己和服务对象可以互换, 在这一点上它与外观不同。

# 参考资料

  • 《Head First 设计模式》 (opens new window)
  • 《大话设计模式》 (opens new window)
  • 设计模式教程 (opens new window)
📝 帮助改善此页面! (opens new window)
#设计#设计模式
上次更新: 2024/01/27, 23:24:21
设计模式之装饰模式
设计模式之享元模式

← 设计模式之装饰模式 设计模式之享元模式→

最近更新
01
设计
04-27
02
微服务简介
04-15
03
如何设计系统
11-08
更多文章>
Theme by Vdoing | Copyright © 2019-2024 钝悟(dunwu) | CC-BY-SA-4.0
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×