以下所有设计模式的源代码:
https://github.com/gloria0610/DesignPattern.git
内容供个人学习理解,需要搭配代码食用。
例子来自HeadFirst设计模式。类图和code手敲,转载请注明。
- 策略模式
定义了算法族,分别封装,并且算法之间可以互相替换。因为每一个算法都被封装起来了,所以客户可以轻易地使用不同算法。
举例:不同的鸭子有不同的飞法和叫法。
我们可以定义一个飞行接口,其子类实现不同种类型的飞行方式,比如翅膀飞(普通鸭子),不会飞(橡皮鸭,木头鸭)
定义一个鸭叫接口。其子类可以是“呱呱叫”,或者“叽叽叫”(橡皮鸭),或者不会叫(木头鸭)。
而不同的鸭子只需要调用接口生成不同的飞行、叫的方法即可。不同鸭子可以使用不同方法,而不关心别的鸭子如何构成。
模型鸭的实现示例:
- 观察者模式
定义了对象之间的一对多依赖,当一个对象改变状态时,其所有依赖者都会收到通知,并自动更新。
例如:气象站的实现。
一个气象站可能有一个气象中心,和多个不同位置的看板。
每一个看板实现:1.接收气象中心的气温更新 2.展示气温 两个功能。
气象中心实现:注册看板,更新气温,移除看板通知的功能。气象站调用update通知其观察者更新看板。
代码示例:
气象中心:
气象看板:
- 装饰模式
咖啡店的例子。每一杯咖啡可以被不同的调料装饰多次。在对象上实现弹性的扩展。
设计原则:类应该对扩展开放,对修改关闭。
首先定义一个Beverage饮料接口,包含描述和费用字段。
以咖啡为例,esprsso是单独的咖啡液,是咖啡的基础类。所以esprsso的代码直接实现饮料接口。
调料类是装饰类,比如拿铁=espresso+milk。所以在所有装饰类内,声明一个饮料类型,再把传入饮料包装起来。
最后再生成产品的时候,可以进行多次包装,只要用不同的类new出来就可以了。
装饰类实例可以被装饰多层。
- 命令模式
一个命令对象通过在特定的接收者上绑定一组动作来封装一个请求。
要达到这一点,命令对象将动作和接受者包进对象中,这个对象只暴露一个execute()方法。
从外面来看,其他对象不知道究竟哪个接收者进行了哪些动作。只知道如果调用execute()方法,请求目的就能达到。
遥控器的例子:在遥控器的不同按钮上都有一个执行操作。不同的对象根据不同的命令实现执行操作。
例如:一个遥控器,既可以控制灯,也可以控制门。
包含灯,及灯的遥控类。门,及门的遥控类。
设计模式(遥控器)统一调用execute()方法执行各自的操作,并不关心每个接收者进行哪些动作。
public class SimpleRemoteControl {
//只要接收者自己定义自己的处理方式,同时实现Command的execute()方法即可,
//设计模式负责统一调用execute()方法执行各自的操作,并不关心每个接收者进行哪些动作
//命令模式统一定义Command的set方法和调用execute()的执行方法即可
Command slot;
public SimpleRemoteControl(){}
public void setCommand(Command command){
slot=command;
}
public void buttonWasPressed(){
slot.execute();
}
}
执行的时候只需要传入特定类的实例,设置按钮,再令其按定义的按钮即可。
- 单例模式
比较典型,拆出来讲。
- 适配器模式
相当于电源转换头。比如接口对应多个厂商的场景。适配器将一个接口转换为另一个接口,以符合客户的期望。适配器让原本不兼容的类可以合作。
比如用火鸡冒充鸭子。
- 模板方法模式
咖啡和茶的共通冲泡法。模板方法定义了一个算法的步骤,并允许子类为一个或多个步骤提供实现。
模板方法模式在一个方法中定义了一个算法的骨架,而将一些步骤延迟到子类中。使得子类在不改变算法结构的情况下,重新定义算法的某些步骤。
抽取出的模板代码,其中共有的方法由父类实现,我们不希望prepare方法被覆盖,声明为final。
子类实现各自的冲泡和添加调料方法。
同时,模板方法可以设定“钩子”,来控制子类是否覆盖或使用某些可选方法。
比如咖啡要不要加调料。
荒野中的模板方法:数组排序。
我们可以使用模板来排序鸭子。
- 迭代器模式
- 组合模式
我们需要某种树形结构,可以容纳菜单,子菜单和菜单项。
我们需要确定能够在每个菜单的各个项之间游走,而且至少要像现在用迭代器一样方便。
也需要能够更有弹性的在菜单项之间游走。比方说:可能只需要遍历单个菜单,也可以遍历整个菜单。
所以引出组合模式的定义:
组合模式允许将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象和对象组合。