设计模式

命令模式

命令模式将"请求"封装成(命令)对象,以便使用不同的请求、队列或者日志来参数化其他对象。 命令模式也支持撤销的操作。

命令模式是一种行为设计模式,它可将请求转换为一个包含与请求相关的所有信息的独立对象。该转换让你能根据不同的请求将方法参数化、延迟请求执行或将其放入队列中,且能实现可撤销操作。

设计原则 #

  1. 解耦:命令模式使发起者和接收者解耦。发起者不关心具体的接收者,只需要根据已知的命令对象 执行execute()方法即可。

UML简图 #

classDiagram
direction LR
class Invoker {
    +Command command
    +invoke()
}
Invoker *..> Command
class Command {
    << interface >>
    +execute()
    +undo()
}
ConcreteCommand ..|> Command
class ConcreteCommand {
    Receiver receiver
    +execute()
    +undo()
}
Receiver <--* ConcreteCommand
class Receiver {
    +someOperation()
}

要点 #

  1. 命令模式将发出请求的对象(调用者)和接收请求的对象(接收者)解耦。
  2. 被解耦的对象之间通过命令对象沟通,命令对象封装了接收者和一个或者一组动作。
  3. 调用者通过执行命令对象的execute()方法发出请求,这会使得接收者的动作被调用。
  4. 调用者接收命令作为参数。甚至可以在运行时动态地进行。
  5. 命令支持撤销。
  6. 宏命令是命令的简单延伸,允许一次调用多个命令。宏命令也支持撤销。
  7. 命令也可以用来实现日志和事务系统。How to?

示例代码 #

在本次示例中,假如你有一个家庭影院,你想通过一个“开关”来一键开启家庭影院,按下这个开关后,系统会执行打开空调,调暗灯光,打开CD播放影片等等一系列操作,我们使用命令模式来完成对应的操作。

...

单例模式

  • by Head First 设计模式

    单例模式确保一个类只有一个实例,并且提供一个全局访问点。

  • by Dive into Design Patterns

    Singleton is a creation(al) design pattern that lets you ensure that a class has only one instance, while providing a global access point to this instance.

...

工厂方法模式

  • by Head First 设计模式

    工厂方法模式定义了一个创建对象的接口,但是由子类决定要创建的对象是哪一个。工厂方法把类的实例化推迟到 子类。

  • by Dive into Design Patterns

    Factory Method is a creation(al) design pattern that provides an interface for creating objects in a superclass, but allows subclasses to alter the type of objects that will be created.

工厂模式指定工厂仅仅能创建特定类型的产品。

...

装饰者模式

  • by Head First 设计模式:

    动态地将责任附加到对象上。若要拓展功能,装饰者模式提供了比继承更有弹性的替代方案。

  • by Dive into Design Patterns:

    Also known as Wrapper

    Decorator is a structural design pattern that lets you attach new behaviors to objects by placing these objects inside special wrapper objects that contain the behaviors.

...

观察者模式

  • by Head First 设计模式

    在对象之间建立一对多的依赖,这样一来,当一个对象的状态改变,依赖它的对象都会收到通知,并且自动更新。

  • by Dive into Design Patterns:

    Also Known as: Event-Subscriber, Listener

    Observer is a behavioral design pattern that lets you define a subscription mechanism to notify multiple objects about any events that happen to the object they’re observing.

...

策略模式

  • by Head First 设计模式:

    策略模式定义了算法族,分别封装起来,让他们之间可以互相替换。此模式让算法的变化独立于使用算法的"客户"。

  • by Dive into Design Patterns:

    Strategy is a behavioral design pattern that lets you define a family of algorithms, put each of them into a separate class, and make their objects interchangeable.

...

适配器模式

适配器模式将一个类的接口,转换成客户期望的另一个接口。 适配器模式可以让原本接口不兼容的类可以合作无间。

设计原则 #

  • 针对接口编程,而不是针对实现编程
  • 多用组合,少用继承
  • 为交互对象之间的松耦合而努力
  • 类应该对拓展开放,而对修改关闭 (开放-关闭原则)
  • 依赖抽象,而不依赖具体类 (依赖倒置原则)

UML简图 #

classDiagram
direction LR
class Client{
    +Adaptor adaptor
    +otherOperations()
}
class Target {
    << Interface >>
    operationA()
}
Client *--> Adaptor
Adaptor ..|> Target
Adaptor *..> Adaptee
class Adaptor {
    +Adaptee adaptee
    operationA()
}
class Adaptee {
    << Interface >>
    operationB()
}

要点 #

  1. 适配器模式,通过创建"适配器"进行接口转换,可以让不兼容的接口变得兼容。
  2. 适配器模式让客户从接口的实现解耦。
  3. 注意适配器和装饰模式的区别,适配器改变接口以让其对不兼容的对象可用, 装饰模式是通过继承,赋予类新的行为和"职责"。
  4. 当需要使用一个现有的类而可用的接口并不适配时,考虑使用适配器模式。

对象适配器和类适配器

...

抽象工厂模式

  • by Head First 设计模式

    抽象工厂模式提供了一个接口,用于创建相关或依赖对象的家族,而不需要指定具体类。 简而言之,抽象工厂可以创建一群对象,而不单单只创建一种对象。这是抽象工厂和工厂方法的区别。

  • by Dive into Design Patterns

    Abstract Factory is a creation(al) design pattern that lets you produce families of related objects without specifying their concrete classes.

...

模板方法模式

模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤 延迟到子类中。模板方法可以使得子类在不改变算法结构的前提 下,重新 定义算法的某些步骤。

...

外观模式

外观模式提供了一个统一的(简单)接口,用来访问子 系统中的一群接口。外观定义了一个高层接口,让系统更 容易使用。

设计原则 #

  • 针对接口编程,而不是针对实现编程
  • 多用组合,少用继承
  • 为交互对象之间的松耦合而努力
  • 类应该对拓展开放,而对修改关闭 (开放-关闭原则)
  • 依赖抽象,而不依赖具体类 (依赖倒置原则)
  • "最少知识原则"——只和你的朋友交谈,不要让太多的类耦合在一起。

最少知识原则:定义 #

在设计系统中,不管是任何对象,都需要注意它所交互的类有哪些,并注意这些类是怎么交互的。

最少知识原则希望,在设计系统的过程中,不要让太多的类交杂在一起,免得修改系统中的一部分, 需要修改其他的部分。如果许多部分相互耦合,系统将会变得复杂、脆弱且不易于维护。

最少知识原则:如何遵循? #

设计系统的过程中,就任何对象而言,在对象的方法内,应该只调用属于一下范畴的方法:

  1. 对象本身的方法
  2. 被当作方法参数而传递进来的对象的方法
  3. 方法内创建或实例化的对象的方法
  4. 对象的任何组件(域、field)的方法

不要调用从上述方法中返回的对象支持的方法。

请看如下例:

1public float getTemp(){
2    Thermometer thermometer = station.getThermometer();
3    return thermometer.getTemperature();
4}

应该优化为:

1public float getTemp(){
2    return  station.getTemperature();
3}

getTemperature方法由station域提供。这样做的好处是,我们 不需要认识Thermometer对象了。让我们始终保持最小的朋友圈!

最少知识原则:缺点 #

是的,任何事情都是两面。最少知识原则使得系统耦合度降低,减轻了维护成本, 但同时禁止调用中间对象的方法,这不得不让我们制造更多的"包装"类来处理和 其他组件之间的沟通,这可能会导致开发难度增加。

让我们接着回到『外观模式』吧。

UML简图 #

外观模式

要点 #

  1. 外观模式中的Facade就是那个"密友",它封装了其他要用到的方法,满足了最少知识原则。
  2. 当要简化并统一一堆接口时,可以使用外观模式。
  3. 外观将客户从一个复杂的系统中解耦。
  4. 实现外观,需要将子系统组合进外观中,然后将具体的工作委托给子系统执行。
  5. 一个复杂的子系统,可以有多个外观。

示例代码 #

外观模式(Facade Pattern)是一种结构型设计模式,它提供了一个统一的接口来访问子系统中的一群接口。外观模式定义了一个高层接口,让子系统更容易使用。

...