设计模式总结
策略模式
提取出变化的行为,封装为接口,多个实现接口的具体类形成一个算法族,让接口对象成为超类的成员变量(即使用组合的方式),在子类中具体设定行为对象(即选择算法族中的具体的一种实现)。
- Strategy:负责决定实现策略所必需的接口。
- ConcreteStrategy:负责实现Strategy角色的接口,实现具体的策略
- Context:负责使用Strategy角色,Context角色保存了ConcreteStrategy角色的实例,并使用ConcreteStrategy去实现需求。
观察者模式
对象之间多对一的依赖关系,被依赖的对象为subject,依赖对象为observer,当subject对象的状态发生变化时,会通知给observer。
适用于根据对象状态进行相应处理的场景。
Java中存在内置的观察者模式,即Observable类对应于subject对象,只要继承这个类,我们自己的subject就自动实现了addObserver()、deleteObserver()、notifyObservers()等方法。只是在通知之前需要先调用setChanged()方法来表示对象状态以及改变。
- Subject(观察对象):定义了注册观察者和删除观察者,通知观察者的方法。
- ConcreteSubject:表示具体的被观察对象。当自身状态发生变化后,会通知所有已经注册的Observer角色
- Observer(观察者):负责接收来自Subject角色的状态变化的通知。定义了update方法。
- ConcreteObserver:表示具体的观察者对象。当它的update方法被调用后,会去获取要观察的对象的最新状态。
装饰者模式
能够动态的添加新功能到对象上,扩展性方面比继承更具有弹性
Component和Decorator都表示为一个抽象类
装饰器Decorator需要继承自被装饰者Component,并且装饰器内部需要持有一个被装饰者Component,这样就可以使用形如
new Decorator(new Decorator(new Decorator(new ConcreteComponent())))
的形式来创建类,并且在Decorator的内部方法中会递归调用其中包含的Component类的对应方法,从而实现新的功能,并且又能调用原有的功能。
这就是Java中的I/O流所采用的装饰者模式。
- Component:增加功能时的核心角色
- ConcreteComponent:实现了Component角色所定义的接口的具体功能表现
- Decorator(装饰物):继承自Component角色,拥有相同的API,在内部保存了被装饰对象——Component角色
- ConcreteDecorator:具体的装饰者对象,负责实现具体的API功能
单例模式
确保一个类最多只有一个实例,并提供一个全局访问点。
单例模式的八种写法
目前开始越来越推崇枚举的单例模式
工厂模式
简单工厂模式
定义了一个创建对象的类,由这个类来封装实例化对象的行为。
工厂方法模式
定义了一个创建对象的抽象方法,由子类决定要实例化的类。将对象的实例化推迟到子类。
Creator为一个抽象类,Product为一个抽象类
抽象工厂模式
定义了一个接口用于创建相关或有依赖关系的对象族,而无需明确指定具体类。
提取出一个工厂接口,具体的多种工厂实现该接口,形成一个工厂族
提取出一个产品接口,具体的多种产品实现该接口,形成一个产品族
Client中包含一个抽象工厂,该角色会调用AbstractFactory和AbstractProduct的接口来进行工作,对于具体的产品和工厂一无所知。通过该抽象工厂创建抽象产品,当传入具体工厂时,则完成了对应的具体产品的实例化。
命令模式
将请求、命令、动作等封装成对象,并使用这些对象参数化其他对象,使得命令的请求者和发动者解耦。
- Command(命令):负责定义命令的接口
- ConcreteCommand(具体的命令):负责实现在Command角色中定义的接口
- Receiver(接收者):是Command角色执行命令时的对象,是命令的接收者
- Client(请求者):负责生成ConcreteCommand角色并分配Receiver角色
- Invoker(发动者):是开始执行命令的角色,会调用在Command中定义的接口
适配器模式
将一个类的接口转换为另一个类的接口,让原本接口不兼容的类可以兼容。
对象适配器和类适配器使用了不同的方法实现适配,类适配器采用继承的方式,对象适配器采用组合的方式。
- Target:负责定义所需的方法
- Client:负责使用Target角色所定义的方法进行具体处理
- Adaptee(被适配者):是一个持有既定方法的角色
- Adapter(适配器):通过继承或组合的方式使用Adaptee角色的方法来满足Target角色的需求。
外观模式
提供一个统一的接口,来访问子系统中的一群功能相关接口
- Facade:代表构成系统的许多其他角色的简单外观
- Client:负责调用Facade角色
- 构成系统的多个其他角色
模板模式
封装了一个算法步骤,并允许子类对一个或多个步骤提供实现。
模板模式可以使得子类在不改变算法步骤的情况下,重新定义算法中的某些步骤。
- AbstractClass:负责实现模板方法,并负责声明模板方法中所使用的抽象方法。
- ConcreteClass:负责具体实现AbstractClass角色中定义的抽象方法。这些方法会在AbstractClass中的模板方法中被调用。
迭代器模式
提供一种方法顺序访问一个聚合对象中的各个对象。
Iterator(迭代器):负责定义按顺序逐个遍历元素的接口
ConcreteIterator:负责实现Iterator角色所定义的接口,包含了遍历集合所必需的信息。
Aggregate(集合):负责定义创建Iterator角色的接口
ConcreteAggregate:负责实现Aggregate角色所定义的接口,会创建出具体的Iterator角色。
组合模式
将对象聚合成树型结构来表现“整体/部分”的层次结构
组合模式使得能用一致的方法来处理个别对象和对象的组合。
- Leaf:表示一个内容的角色
- Composite:表示容器角色,其中可以放入Leaf和Composite
- Compont:使Leaf和Composite具有一致性的角色,是Leaf和Composite的抽象父类
- Client:使用Compont的角色。
状态模式
用类来表示状态,可以通过切换类来方便地改变对象的状态。根据内部状态的变化,改变类的行为,看起来就像是改变了类一样。
使用状态模式的好处是,当需要增加新的状态时,可以通过创建新的状态类来实现功能。
- State:表示状态,定义了根据不同状态进行不同处理的接口,是处理内容依赖于状态的方法的集合
- ConcreteState:表示各个具体的状态
- Context:持有表示当前状态的ConcreteState角色。还定义了供外部调用者使用State模式的接口
代理模式
- Proxy:会尽量处理来自Client角色的请求,只有当自己不能处理时,才会将工作交给RealSubject角色
- RealSubject:实际完成任务的角色
- Client:任务请求者
动态代理
运行时动态的创建代理类对象,并将方法调用转发到指定类。
桥接模式
将实现与抽象放在两个不同的类层次中,使两个层次可以独立改变。
- Abstraction:类的功能层次的最上层
- RefinedAbstraction(改善后的抽象化):再Abstraction的基础上增加了新功能的角色
- Implementor(实现者):类的实现层次的最上层,定义了用于实现Abstraction角色的接口的方法
- ConcreteImplementor:负责实现再Implemontor角色中定义的接口
生成器模式
Builder模式用于创建具有复杂结构的对象实例。封装了一个复杂对象的构造过程,并允许按步骤构造。
- Builder:负责定义用于生成实例的接口
- ConcreteBuilder:负责实现Builder角色的接口的类,还定义了获取最终生成结果的方法。
- Director:负责使用Builder角色的接口来生成实例,只调用在Builder中被定义的方法。
责任链模式
将多个对象组成一条责任链,然后按照它们在责任链上的顺序,找出应该由谁来处理。
- Handler:定义了处理请求的接口
- ConcreteHandler:处理请求的具体角色
- Client:是向第一个ConcreteHandler角色发送请求的角色。
享元模式
通过尽量共享实例来避免new出实例
- Flyweight: 实例被共享的类
- FlyweigthFactory: 生成Flyweight角色的工厂
- Client: 使用FlyweightFactory:使用FlyweigthFactory来生成Flyweight角色
解释器模式
定义一个语法,定义一个解释器,该解释器处理这个语法句子
将某些复杂问题表达为某种语法规则,然后构建解析器来解释处理这类句子
- AbstractExpression:定义了语法树节点的共同API
- TerminalExpression:BNF的终止表达式
- NonterminalExpression:BNF的非终止表达式
- Context:为解释器进行语法解析提供必要信息
中介者模式
用一个中介对象来封装一系列的对象交互。
中介者模式使得各个对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
- Mediator(中介者):负责定义与Colleague角色进行通信和做决定的接口
- ConcreteMediator:负责实现Mediator角色的API,负责实际做出决定
- Colleague(同事):负责定义与Mediator角色进行通信的API
- ConcreteColleague:负责实现Colleague角色的API
备忘录模式
在不破坏封装的前提下,存储关键对象的重要状态,从而可以在将来把对象还原到存储的那个状态。
- Originator(生成者):会在保存自己的最新状态时生成Memento角色;当把以前保存的Memento角色传递给Originator角色时,会将自己恢复至生成该Memento角色时的状态。
- Memento:会将Originator角色的内部信息整合在一起,但不会向外公开这些信息。
- Caretaker(负责人):当Caretaker角色想要保存当前的Originator角色的状态时,会通知Originator角色。Caretaker只能访问Memento角色的窄接口,即不能访问具体的内部信息,只是将Originator角色生成的Memento角色当作一个黑盒子保存起来。
原型模式
通过复制现有实例来创建新的实例,无须知道相应类的信息
- Prototype(原型):负责定义用于复制现有实例来生成新实例的方法。
- ConcretePrototype:负责实现复制现有实例并生成新实例的方法。
- Client:负责使用复制实例的方法生成新的实例。
访问者模式
对于一组对象,在不改变数据结构的前提下,增加作用于这些结构元素新的功能。
- Visitor(访问者):负责对数据结构中每个具体的元素声明一个用于访问XXX的visit(XXX)方法。
- ConcreteVisitor:负责实现Visitor角色所定义的API
- Element:表示Visitor角色的访问对象
- ConcreteElement:负责实现Element角色所定义的API
- ObjectStructure:负责处理Element角色的集合