Java是一门非常彻底的OO语言,因此JDK以及各种框架的源码都有很强的设计模式的影子。
设计模式其实是软件工程发展出来的,说到设计模式不得不提的6大准则:
1.开闭原则(Open Close Princeple)
对扩展开放,对修改关闭
2.里氏替换原则(Liskov Substitution Princeple)
衍生类替换掉基类,要保证软件单位的功能不受到影响时,是开闭原则的一种具体体现
3.依赖倒转原则 (Dependence Inversion Principle)
对接口编程,依赖于抽象而不依赖于具体。
4.接口隔离(Interface Segregation Princeple)
简言之,就是要降低耦合度,不要把所有功能(鸡蛋)放在一个篮子里,提高复用能力
5.迪米特法则(最少知道原则)(Demeter Princeple)
实体之间减少暴露,少发生作用,功能要独立,不要强依赖
6.合成复用原则(Composite Reuse Princeple)
在第5点的基础上,如果要发生联系,尽量使用合成/聚合方式,而不要使用继承
设计模式大体上分为三大类:
创建型模式(5种):工厂模式,抽象工厂模式,单例模式,建造者模式,原型模式。
结构型模式(7种):适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模式,享元模式。
行为型模式(11种):策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
第一篇章 创建型模式
1.单例模式:
new Object()可以复用的Object没有必要不断实例,单例碰到并发怎么办? 当然是经典的synchronized双重==null+volitaile,内部静态类static单例,枚举单例,或者final安全发布。
2.工厂模式:
常用的工厂模式是静态工厂,利用static方法返回一个新实例,作为一种类似于常见的工具类Utils等辅助效果,一般情况下工厂类不需要实例化。
3.抽象工厂模式:
我个人把它理解为流水线,当工厂不断增加的同质化产品,需要引入同质化的生产线,那么就通过接口抽象一层,可以把产品抽象,同时也把生产线抽象。是一种多样化的工厂模式。
4.建造者模式:
链式传播,前端用的很多的,build & 返回this ,可以用内部类
5.原型模式:
想到了JS的prototype,基于对象编程而不是OO那一套,更贴近对象本质,OO的核心是抽象,多态,而JS那套是引用的复制粘贴,Java嘛,clone()浅克隆
第二篇章 结构型模式
1.适配器模式(Adapter):
老的类实现老的接口,但想要增加新功能,怎么办?千万不要直接在老类上改!可以搞个新类继承一下这个老类,顺便实现个新接口。开闭原则和里氏替换原则,不过其实有三种方法的
a.类适配:创建新类,继承源类,并实现新接口,例如
public interface Usb {
void isUsb();
}
public class Usber implements Usb {
@Override
public void isUsb() {
System.out.println("USB口");
}
}
publicinterface Ps2 {
void isPs2();
}
public class Adapter extends Usber implements Ps2 {
@Override
public void isPs2() {
isUsb();
}
}
b.对象适配: 当我们要访问的接口A中没有我们想要的方法,却在另一个接口B中发现了合适的方法,我们又不能改变访问接口A,在这种情况下,我们可以定义一个适配器p来进行中转,这个适配器p要实现我们访问的接口A,这样我们就能继续访问当前接口A中的方法(虽然它目前不是我们的菜),然后在适配器P中定义私有变量C(对象)(B接口指向变量名),再定义一个带参数的构造器用来为对象C赋值,再在A接口的方法实现中使用对象C调用其来源于B接口的方法。还以上面的例子:
public class Adapter implements Ps2 {
private Usb usb;
public Adapter(Usb usb){
this.usb = usb;
}
@Override
public void isPs2() {
usb.isUsb();
}
}
c.接口适配:接口方法太多,有些不想实现,做一个中间层Adapter
public interface A {
void a();
void b();
}
public abstract class Adapter implements A {
public void a(){}
public void b(){}
}
public class Ashili extends Adapter {
public void a(){
System.out.println("实现A方法被调用");
}
}
2.装饰器模式(Decorator):
有点像上面的b,但本质不同,很像代理模式但是关注的重点不一样
class Decorator implements oldFunc {
private oldClass oldInstance ;
void oldFunc(){
doSomething...
//这句oldFunc一定要执行,因为我们只是装饰,不然就成了代理模式
oldInstance .oldFunc();
doSomething...
}
}
3.代理模式(Proxy):
class Proxy implements Source {
private Source source;
void source(){
doSomething...
//这句source()一般不会执行,因为代理类对原类有完整控制权 ,代理是一种替换
source.source();
doSomething...
}
}
4.外观模式(Facade):
当使用功能复杂的类集合时候,对外只要提供一个统一开关把各种类统一把控。
5.桥接模式(Bridge):
方法形参或者构造方法形参写成抽象借口,可以动态注入不同的实现,同时多种这样的实现组合起来。
6.组合模式(Composite):
文件夹和文件的目录,上层抽象都是File,但文件夹又可以包含文件,可以a.set(b);b.set(c);c.set(d)...这样不断传播下去。
7.享元模式(Flyweight):
可以理解为缓存模式,hashMap存东西大家都用过把,方便下次再取,取不到说明没有,就存。
第三篇章 行为型模式
1.责任链模式(Chain of Responsibility Pattern):
JS 中的事件冒泡,JavaWeb的Filter ,Spring拦截机制。。。(其实就是个链表,每一个实体持有下一个实体的引用,把功能实现的责任往上抛)
2.迭代器模式 (iterator):
游标cursor模式,用游标实现遍历,java的集合类中colletion都实现了Iterable
3.中介者模式(mediator):
中介就是注册中心,大家都持有中间的引用,注册到中介。大家可以向中介发送指令,中介也可以向大家发送指令。是沟通的桥梁。即时聊天比如QQ就是一种中介
4.命令模式(command):
单向传播的中介者模式就是命令模式,Invoker --> command(特殊中介) --> receiver
5.解析器模式(Interpreter):不常用 看作一种编译器
EL表达式的处理
正则表达式解析器
SQL语法的解析器
数学表达式解析器
6.访问者模式(visitor):
表示一个作用于某对象结构中的各个元素的操作,它使我们可以在不改变元素的类的前提下定义作用于这些元素的新操作
7.策略模式(strategy):
和桥接模式类似,动态注入,1对多
8.模板方法模式(template method):
不多说,其实就是留一个钩子方法等待实现类实现!
9.状态模式(state):
和策略模式类似,不过会自动调用一次注入的实体的固定方法,表示状态代表
10.观察者模式(observer):
我的理解:也是一种特殊的中介者模式,也就是广播模式,有推拉两种,好像消息队列
11.备忘录模式(memento):
实现一种save方法,把自己当前的值保存到一个备忘录对象里去,可以随时从备忘录里取出来