这篇笔记要包括的内容
- 设计原则
- 创造者模式
- 结构型模式
- 行为型模式
- 对比
- JDK中用到的设计模式
设计原则
1、单一职责
2、开放-关闭(可以扩展但别修改)
3、里氏替换(继承父类不要覆盖子类方法)
6、迪米特法则(类只和必要的类保持通信,不要乱接触)
4、依赖倒转(面向接口编程,先给一个通用接口,其他人可以先编程)
5、接口隔离(接口细化、互不干扰)
7、组合/聚合(继承父类改成,设计一个接口,让继承这个接口的类注入到要用的类)
涉及到接口:
接口细化-接口隔离
接口编程-依赖倒转
接口注入-组合/聚合
涉及到类:
类别修改-开放关闭
类别覆盖方法-里氏替换
类别通信-迪米特法则
单一修改
创造者模式
-
工厂方法
https://refactoring.guru/design-patterns/factory-method
product接口:抽象的产品接口
creator接口:抽象的工厂接口
可以分别对每种具体的产品实现一个具体的工厂
-
抽象工厂
https://refactoring.guru/design-patterns/abstract-factory
product接口:抽象的产品接口
creator接口:抽象的工厂接口(但是可以生产一组产品)
可以对每一组结构相似的产品实现一个具体的工厂
不同的操作系统,实现类似的GUI界面
-
建造者模式
https://refactoring.guru/design-patterns/builder
builder接口:抽象的建造者接口
Director类:具体的指导者类
可以实现不同的建造者,注入到指导者里面,让其建造即可
-
原型模式
prototype接口:抽象的原型接口,提供clone方法 继承这个接口,重新clone接口实现即可
-
单例模式
静态方法加线程锁,如果未空创建、否则返回生成的instance
5种写法
1、final+static
2、枚举
3、double checking
4、加class 锁
5、内部类
结构型模式
-
适配器
类适配器:多重继承(c++)、继承两个类,转换一下再调用
接口适配器: 定义一个接口,客户端去调用这个接口,然后对这个接口去实现一个具体的类(adpter),具体的类中注入要适配的类(adptee),转换之后调用adptee就好了
-
桥接
两个维度在变化时,可以用桥接,
(变化维度1)定义一个接口,然后有一些具体的类实现这些接口,提供具体方法拱变化维度2去调用
(变化维度2)定义一个抽象类包含一些抽象方法,把上面的接口注入进来,然后后面可以有一些类继承它,这里的方法实现依赖于注入的类(实现了变化维度1的接口)去调用,
-
组合模式
定义一个抽象的组件接口 一个具体的叶子节点类去实现这个接口, 一个具体的非叶子节点类去实现接口,这个类里面再注入一些组件接口(具体视调用而定)
-
装饰器
定义一个抽象的组件接口(要被装饰)
一个具体的组件类(要被修饰,继承上面接口)
一个抽象的装饰器类(继承上面接口,注入组件接口而非具体组件类)
一个具体的抽象器类(继承,增加额外方法)
-
外观模式
封装系统功能方便调用
-
享元模式(flyweight)
内存中共享公共的数据(常量)
享元工厂 享元(公共的数据,具体的实现在这里)
上下文(独立的数据,调用)
总的来说便是抽取公共的部分进行共享。只会保存一份公共数据,防止空间重复。
-
代理模式
代理公共接口
实现上述接口类:被代理类(注入到代理类里面)、代理类(增加一些增强操作)
行为型模式
-
责任链模式
-
命令模式
-
迭代器模式
-
中介者模式
-
备忘录模式
-
观察者模式
-
状态模式
-
策略模式
-
模板方法模式
-
访问者模式
对比
-
相似:适配器、装饰器、代理模式
装饰器和代理结构类似,
代理模式中的被代理的类自己管理整个使用周期 而装饰器则需要自己手动去装配
JDK中用到的设计模式
抽象工厂
javax.xml.parsers.DocumentBuilderFactory抽象类
public static DocumentBuilderFactory newInstance()方法
类功能:使得应用程序可以通过XML文件,获得一个能生成DOM对象的解析器。
方法功能:获取一个DocumentBuilderFactory的新实例。这一静态方法会创建一个新的工厂实例。
建造者模式
java.lang.StringBuilder,这是一个final类
public StringBuilder append(String str)方法,这一方法是对父类的覆写。
类功能:用于一个不可更改的字符序列。
方法功能:根据现有字符序列和追加字符,通过系统拷贝方法System.arraycopy生成一个新的字符序列。
工厂模式
java.text.NumberFormat抽象类
public final static NumberFormat getInstance()方法
类功能:用于数字格式的抽象基类。
方法功能:返回一个“对当前默认场景下的一个通用数字格式”的NumberFormat。显然属于工厂模式的使用。
原型模式
java.lang.Object
protected native Object clone() 方法
类功能:所有类的父类
方法功能:根据现有实例,返回一个浅拷贝对象。
单例模式
java.lang.RunTime类
public static Runtime getRuntime()
类功能:每一个运行的java应用都会有一个唯一的RunTime类的实例,这个实例使得应用程序在运行期间能够受到运行环境的影响。
方法功能:返回一个和当前java应用关联的RunTime对象。
适配器模式
java.util.Arrays
public static List asList(T… a)方法
类功能:此类包含了大量对数组操作的方法。
方法功能:将一个引用类型的数组转为一个List。从而可以使用List类的操作来操作数组对象,但是有一点要注意:就是不能使用add(),remove()操作,因为返回的list底层是基于数组的,数组结构是不能更改的。 list类就是这里的适配器,通过这个适配器,对数组的直接操作变为间接操作。
桥接模式
目前没有找到
组合模式
java.awt.Container类
public Component add(Component comp)方法
类功能:一个通用的AWT(Abstract Window Toolkit)容器,能够用于存储其它AWT组件。
方法功能:添加一个AWT组件到容器中。
享元模式
java.lang.Integer(其它基本类型包装类(除去Float,Double)也如此,还有BigDecimal)
Integer.valueOf()方法
byte,short,int,long,boolean,char的包装型在类加载到JVM时,已经缓存了制定范围的对象引用,因为值的设定使用的是static块或者常量。其中char的范围为:0~127;boolean的值为true和false;其它默认范围都是-127~128。其中int的上限127可以调整,这需要调整JVM的参数。
同时利用了享元模式的还有String这个类,因为生存的每个字符串都是不可变的。
代理模式
java.lang.reflect.Proxy类
原理:代理提供了一个static方法用于创建一个动态代理类和被代理类的实例。它是所有通过此方式创建动态代理类的父类。
职责链模式
java.util.logging.Logger类
public void log(LogRecord record)
类功能:为系统or组件记录日志消息。如何体现了职责链模式:每个记录器都跟踪“父”记录器,所谓”父”记录器,就是Logger命名空间中最近的现有祖先。
方法功能:用于记录日志信息。这一类中所有其它的日志方法都是通过调用这一方法实现日志记录的。子类能够覆写这一方法从而获取所有的日志行为。
迭代器模式
这个就不说了,很多集合已经使用了迭代器进行遍历。
策略模式
java.util.Comparator函数接口
compare()方法
比较器的使用就是:先写一个比较器,然后对Arrays或者Collections排序的时候,将写好的比较器作为参数传入排序的方法,就能实现按照比较器的规则,对Arrays或者Collections进行排序。
比较器方法如何体现策略模式的:策略模式是指:一个类/接口A的行为方法的执行,是通过调用另一个不同的类/接口B而实现的。调用方式是将B作为A的传入参数。这和Comparator的原理完全一致。