前言
总体来说设计模式分为三大类:
创建型模式: 工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式: 适配器模式、装饰模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式: 策略模式、模板方法模式、观察者模式、迭代器模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
下列以原型模式、代理模式、迭代器模式为例:
原型模式
概念
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
使用场景
资源优化场景: 类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。
性能和安全要求的场景: 通过 new 产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。
一个对象多个修改者的场景: 一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。
优点
原型模式实际上就是实现 Cloneable 接口,重写 clone()方法。
性能优良: 原型模式是在内存中二进制流的拷贝,要比直接 new 一个对象性能好很多,特别是要在一个循环体内产生大量的对象时,原型模式可以更好地体现其优点。
逃避构造函数的约束: 这既是它的优点也是缺点,直接在内存中拷贝,构造函数是不会执行的。
代码实践
public class PrototypeClass implements Cloneable{
//覆写父类 Object 方法
@Override
public PrototypeClass clone(){
PrototypeClass prototypeClass = null;
try {
prototypeClass = (PrototypeClass)super.clone();
} catch (CloneNotSupportedException e) {
//异常处理
}
return prototypeClass;
}
}
代理模式
概念
为其他对象提供一种代理以控制对这个对象的访问。
结构
Subject 抽象主题角色: 抽象主题类可以是抽象类也可以是接口,是一个最普通的业务类型定义,无特殊要求。
RealSubject 具体主题角色: 也叫做被委托角色、被代理角色。它才是冤大头,是业务逻辑的具体执行者。
Proxy 代理主题角色: 也叫做委托类、代理类。它负责对真实角色的应用,把所有抽象主题类定义的方法、限制委托给真实主题角色实现,并且在真实主题角色处理完毕前后做预处理和善后处理工作。
分类
普通代理: 在该模式下,调用者只知代理而不用知道真实的角色是谁,屏蔽了真实角色的变更对高层模块的影响,真实的主题角色想怎么修改就怎么修改,对高层次的模块没有任何的影响,只要你实现了接口所对应的方法,该模式非常适合对扩展性要求较高的场合。
强制代理: 强制代理的概念就是要从真实角色查找到代理角色,不允许直接访问真实角色。高层模块只要调用 getProxy 就可以访问真实角色的所有方法,它根本就不需要产生一个代理出来,代理的管理已经由真实角色自己完成。
- 区别:普通代理就是我们要知道代理的存在,然后才能访问;强制代理则是调用者直接调用真实角色,而不用关心代理是否存在,其代理的产生是由真实角色决定的。
动态代理: 根据被代理的接口生成所有的方法,也就是说给定一个接口,动态代理会宣称“我已经实现该接口下的所有方法了”。两条独立发展的线路。动态代理实现代理的职责,业务逻辑实现相关的逻辑功能,两者之间没有必然的相互耦合的关系。通知从另一个切面切入,最终在高层模块进行耦合,完成逻辑的封装任务。
- 意图:横切面编程,在不改变我们已有代码结构的情况下增强或控制对象的行为。
- 首要条件:被代理的类必须要实现一个接口。
代码实践
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
迭代器模式
概念
它提供一种方法访问一个容器对象中各个元素, 而又不需暴露该对象的内部细节。
结构
Iterator 抽象迭代器: 抽象迭代器负责定义访问和遍历元素的接口,而且基本上是有固定的 3 个方法:first() 获得第一个元素,next() 访问下一个元素,isDone() 是否已经访问到底部(Java 叫做 hasNext() 方法)。
ConcreteIterator 具体迭代器: 具体迭代器角色要实现迭代器接口,完成容器元素的遍历。
Aggregate 抽象容器: 容器角色负责提供创建具体迭代器角色的接口,提供一个类似 createIterator() 这样的方法,在 Java 中一般是 iterator() 方法。
Concrete Aggregate 具体容器: 具体容器实现容器接口定义的方法,创建出容纳迭代器的对象。
代码实践
/**
* 具体迭代器
*/
public class ConcreteIterator<T> implements Iterator<T> {
private List<T> list = new ArrayList<>();
private int cursor = 0;
public boolean hasNext() {
return cursor != list.size();
}
public T next() {
T obj = null;
if (this.hasNext()) {
obj = this.list.get(cursor++);
}
return obj;
}
}
总结
通过文章总结出抽象的模式相对简单,但是套用到实际应用中却并不简单,必须以实践为主,才是优秀项目的master key。