算是读书笔记吧
极客时间--设计模式之美
代理模式和装饰器模式的在实现上相同,所以放在一起看。
以代理模式为例
// 代理模式的代码结构(下面的接口也可以替换成抽象类)
public interface IA {
void f();
}
public class A impelements IA {
public void f() { //... }
}
public class AProxy impements IA {
private IA a;
public AProxy(IA a) {
this.a = a;
}
public void f() {
// 新添加的代理逻辑
a.f();
// 新添加的代理逻辑
}
}
private void demo() {
IA a = AProxy(A.new())
a.f()
}
二者的相似性
-
目的上
主要解决继承关系过于复杂的问题,借助面向接口的编程思想,通过组合来替代继承。
-
实现上
在不改变原始类(或叫被代理类)代码的情况下,由新的类和原始类需要实现相同的接口。
二者的区别性
二者的区别体现在想要对原始类附加的功能
代理模式
将功能直接转交给代理类进行实现。
偏重业务无关,高度抽象,和稳定性较高的场景。
由原始类指定代理类,对业务方隐藏代理类的存在。
比如对数据访问功能添加日志,缓存。
装饰器模式
给原始类添加增强功能。
偏重业务相关,定制化诉求高,改动较频繁的场景。
由业务方指定装饰类,依赖业务方的具体实现。
比如业务级别上对日志增加字段、数据的加工整理。
代理模式主要目的是控制访问,而非加强功能。这是它跟装饰器模式最大的不同
适配器模式
适配器模式与代理和装饰器模式一样,也是基于面向接口编程的特性,通过接口对不同的类进行统一约束。
这里的统一,体现在:
- 不同类的调用方式统一,更好的利用多态特性
// 使用适配器模式进行改造
public interface ISensitiveWordsFilter { // 统一接口定义
String filter(String text);
}
// 扩展性更好,更加符合开闭原则,如果添加一个新的敏感词过滤系统,
// 这个类完全不需要改动;而且基于接口而非实现编程,代码的可测试性更好。
public class RiskManagement {
private List<ISensitiveWordsFilter> filters = new ArrayList<>();
public void addSensitiveWordsFilter(ISensitiveWordsFilter filter) {
filters.add(filter);
}
public String filterSensitiveWords(String text) {
String maskedText = text;
for (ISensitiveWordsFilter filter : filters) { //这里每个filter的filter方法内部,包裹着真实实现
maskedText = filter.filter(maskedText);
}
return maskedText;
}
}
当然,也有为了版本兼容而使用的适配器模式。将适配器实现的细节,转接给另一个类进行实现
/**
* Returns an enumeration over the specified collection. This provides
* interoperability with legacy APIs that require an enumeration
* as input.
*
* @param <T> the class of the objects in the collection
* @param c the collection for which an enumeration is to be returned.
* @return an enumeration over the specified collection.
* @see Enumeration
*/
public static <T> Enumeration<T> enumeration(final Collection<T> c) {
return new Enumeration<T>() {
private final Iterator<T> i = c.iterator();
public boolean hasMoreElements() {
return i.hasNext();
}
public T nextElement() {
return i.next();
}
};
}
适配器模式是用来做适配,它将不兼容的接口转换为可兼容的接口,让原本由于接口不兼容而不能一起工作的类可以一起工作。适配器模式有两种实现方式:类适配器和对象适配器。其中,类适配器使用继承关系来实现,对象适配器使用组合关系来实现。
一般来说,适配器模式可以看作一种“补偿模式”,用来补救设计上的缺陷。应用这种模式算是“无奈之举”,如果在设计初期,我们就能协调规避接口不兼容的问题,那这种模式就没有应用的机会了。