Java设计模式学习总结
设计模式是一些场景下的设计经验的总结。
学习设计模式不应把掌握所有的设计套路为目标,而是应该理会设计的思想,明白为何会有这些设计模式,每个模式是为了解决什么问题,在什么场景下会有什么样的效果。
只有多思考这些设计模式存在的意义,结合设计的方法,再尝试着在合适的场景下应用合适的模式,才是正确的方式。
下面是我在学习《HEAD first设计模式》所做的一些记录,比较精简,主要是记录了模式的设计思想和解决的问题,仅供大家学习参考。
要想根据这些文字就能掌握好设计模式,是不可能的。所以大家还是要多实践、多思考、多总结。
设计思想:
面向接口编程;
应对变化(数量、类型、扩展),封装变化;
(一)设计原则
1. 封装变化
2. 多用组合,少用继承
3. 针对接口编程,不针对实现编程
4. 为交互对象之间的松耦合设计而努力
5. 开闭原则(对扩展开放,对修改关闭)
6. 依赖倒置原则:要依赖抽象,不要以来具体类
*变量不可以持有具体类的引用
*不要让类派生自具体类
*不要覆盖基类中已实现的方法
7. 最少知识原则:只和你的密友谈话(减少模块间耦合)
将方法调用保持在界限内。
在对象的方法内,我们只应调用以下范围的方法:
a) 该对象本身
b) 被仿作方法的参数而传递进来的对象
c) 此方法所创建或实例化的任何对象
d) 对象的任何组件
8. 好莱坞原则
别调用我们,我们会调用你。(Donot call me, i'll call you)
防止依赖腐败,避免明显的环状依赖。
9. 单一责任(单一职责原则)
一个类应该只有一个引起变化的原因。
(二)设计模式
1. 策略模式(StrategyPattern)
解决算法族的动态切换及扩展性问题
2. 观察者模式(ObserverPattern)
use: Observable/Observer
解决一对多的通知以及被通知者的动态扩展问题
3. 装饰者模式(DecoratorPattern)
职责扩充
eg.InputStream->FilterInputStream
借用继承实现相同接口对象的引用及扩展,赋予新的职责
(动态的将责任附加到对象上,用于扩展功能)
4. 工厂方法模式(FactoryPattern)
use:FactoryClass/Abstract Factory(abstract createComponent)
封装实现,应对实例化类型及数量的变化。
通过Abstract类声明工厂方法,子类继承并分别实现工厂方法。
工厂方法将类的实例化推迟到了子类。
误区:简单工厂方法被误认为是工厂模式。简单工厂类提供一个create方法,
直接将生产过程放在该方法中实现。和工厂方法的abstract方法有所区分。
5. 抽象工厂模式(Abstract Factory Pattern)
提供一个接口,用于创建相关或依赖对象的家族,而不需要指定具体类。
6. 单例模式(Singleton)
线程不安全:
普通方式
线程安全三种方式:
同步getInstance()方法(最差)
急切实例化(类初始化时直接将变量实例化)
双重检验加锁:延迟实例化的最佳方案
7. 命令模式(Command Pattern)
将请求封装成对象
完成操作与实现的解耦(打包运算块),还可以实现撤销。
Invoker: public static void main() { Receiver receiver = new Receiver(); receiver.setCommand(command); } Receiver: private Command = command; public void setCommand(Command command) { this.command = command; } public void receiveEvent(Event event) { if(event == DO_Event) command.execute(); if(event == UNDO_Event) command.undo(); } Interface<<Command>>: public void execute(); public void undo();
应用:
a. 产出命令后,放入commandQueue,专门的线程池负责从commandQueue中取command执行
b. 记录已执行但未彻底结束的操作,持久化到硬盘,实现异常恢复(未保存的word操作)
8. 适配器模式
解决接口不兼容问题,完成接口的转换。
9. 外观模式(Facade Pattern)
组合实现,简化接口。提供一个统一接口(高层接口),访问子系统中的一群接口。
10. 模板方法模式(Template Pattern)
在一个方法中定义一个算法(一组步骤)的骨架,将一些具体的实现步骤延迟到子类中完成。
这样可以保证子类不改变算法的框架。
模板中创建一个钩子,可以实现子类对父类的反向控制:
SuperClass: public void process() { if(customerNeedAddCondiments()) addCondiments(); } boolean customerNeedAddCondiments() { return true; } SubClass: @Override boolean customerNeedAddCondiments() { if(askCustomer() == "yes") return true; else return false; } String askCustomer() { return "yes"; }
应用:排序功能,由子类实现int CompareTo();
11. 迭代器模式(Iterator Pattern)
提供了一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。
Menu{MenuItem[] menuItems; MenuIterator createIterator();}
Iterator <|- - - - MenuIterator
12. 组合模式(Composite Pattern)
将对象组成树形结构来表示整体与部分的层次结构。组合可以让客户以统一的方式处理个别对象以及对象组合。
解决整体、部分关系对象的关系问题,提供了一种统一的处理方案(类似树)
Menu/MenuItem -----|> MenuComponent
leaf/node
并据此设计一种iterator方案
13. 状态模式(State Pattern)
将状态变化及不同状态时行为的不同封装进不同的状态类。
状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
14. 代理模式(Proxy Pattern)
控制对象的访问的中间层
eg.远程代理:(RMI传输调用)
本地客户对象-->客户辅助对象(代理)-----||----->服务辅助对象-->服务对象
______________本地________________________--___________远程____________
RMI将客户服务对象称为桩stub,将服务辅助对象称为骨架scheleton
代理模式为另一个对象提供一个替身或占位符以控制对这个对象的访问。
几种代理控制访问的方式:
a. 远程代理控制访问远程对象
b. 虚拟代理控制访问创建开销大的资源
例如ImageProxy代理Image,避免了创建image下载图片时的阻塞,显示等待界面
c. 保护代理基于权限控制对资源的访问
15. 桥接模式(Bridge Pattern)
分类抽象接口及其实现,将继承转化为关联,提高系统的可扩展性。
eg.画图类中,将Color的设计脱耦单独实现,面对Color的扩展。
16. 责任链模式 (Chain of Responsibility Pattern)
将事件的一系列处理器,连接成一个链表。在事件到来时,依次传递处理。
若当前处理器可以处理,则直接处理并结束;否则,将事件传递给下一个处理器进行处理。
责任链模式将事件的发送者与接受者解耦,并允许动态的新增或者删除责任。
17. 享元模式(Flyweight Pattern)
通过共享技术,有效支持大量的细粒度对象。
flyweight存储内部状态(不受外部环境影响)
18. 解释器模式
19. 中介者模式(Mediator Pattern)
在多个对象交互中间环节添加一个中介者,用来实现对象彼此的解耦,增加对象的复用性,
简化对象之间的消息传递。
20. 备忘录模式(Memento Pattern)
储存系统关键对象的重要状态(save)
维护关键对象的封装(get)
21. 原型模式
通过clone或者反序列化把一个已有的对象当做原型进行直接复制。
需要注意的是,常规的clone方法是浅克隆。
需要clone的类需要实现Cloneable接口。
22. 生成器模式(Builder Pattern)
管理复杂对象的创建工作(通常包含组合结构)