算是讀書筆記吧
極客時間--設計模式之美
代理模式和裝飾器模式的在實現上相同,所以放在一起看。
以代理模式爲例
// 代理模式的代碼結構(下面的接口也可以替換成抽象類)
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();
}
};
}