
算是讀書筆記吧
極客時(shí)間--設(shè)計(jì)模式之美
代理模式和裝飾器模式的在實(shí)現(xiàn)上相同,所以放在一起看。
以代理模式為例
// 代理模式的代碼結(jié)構(gòu)(下面的接口也可以替換成抽象類)
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()
}
二者的相似性
-
目的上
主要解決繼承關(guān)系過于復(fù)雜的問題,借助面向接口的編程思想,通過組合來替代繼承。
-
實(shí)現(xiàn)上
在不改變?cè)碱悾ɑ蚪斜淮眍悾┐a的情況下,由新的類和原始類需要實(shí)現(xiàn)相同的接口。
二者的區(qū)別性
二者的區(qū)別體現(xiàn)在想要對(duì)原始類附加的功能
代理模式
將功能直接轉(zhuǎn)交給代理類進(jìn)行實(shí)現(xiàn)。
偏重業(yè)務(wù)無關(guān),高度抽象,和穩(wěn)定性較高的場景。
由原始類指定代理類,對(duì)業(yè)務(wù)方隱藏代理類的存在。
比如對(duì)數(shù)據(jù)訪問功能添加日志,緩存。
裝飾器模式
給原始類添加增強(qiáng)功能。
偏重業(yè)務(wù)相關(guān),定制化訴求高,改動(dòng)較頻繁的場景。
由業(yè)務(wù)方指定裝飾類,依賴業(yè)務(wù)方的具體實(shí)現(xiàn)。
比如業(yè)務(wù)級(jí)別上對(duì)日志增加字段、數(shù)據(jù)的加工整理。
代理模式主要目的是控制訪問,而非加強(qiáng)功能。這是它跟裝飾器模式最大的不同
適配器模式
適配器模式與代理和裝飾器模式一樣,也是基于面向接口編程的特性,通過接口對(duì)不同的類進(jìn)行統(tǒng)一約束。
這里的統(tǒng)一,體現(xiàn)在:
- 不同類的調(diào)用方式統(tǒng)一,更好的利用多態(tài)特性
// 使用適配器模式進(jìn)行改造
public interface ISensitiveWordsFilter { // 統(tǒng)一接口定義
String filter(String text);
}
// 擴(kuò)展性更好,更加符合開閉原則,如果添加一個(gè)新的敏感詞過濾系統(tǒng),
// 這個(gè)類完全不需要改動(dòng);而且基于接口而非實(shí)現(xiàn)編程,代碼的可測試性更好。
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) { //這里每個(gè)filter的filter方法內(nèi)部,包裹著真實(shí)實(shí)現(xiàn)
maskedText = filter.filter(maskedText);
}
return maskedText;
}
}
當(dāng)然,也有為了版本兼容而使用的適配器模式。將適配器實(shí)現(xiàn)的細(xì)節(jié),轉(zhuǎn)接給另一個(gè)類進(jìn)行實(shí)現(xiàn)
/**
* 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();
}
};
}
適配器模式是用來做適配,它將不兼容的接口轉(zhuǎn)換為可兼容的接口,讓原本由于接口不兼容而不能一起工作的類可以一起工作。適配器模式有兩種實(shí)現(xiàn)方式:類適配器和對(duì)象適配器。其中,類適配器使用繼承關(guān)系來實(shí)現(xiàn),對(duì)象適配器使用組合關(guān)系來實(shí)現(xiàn)。
一般來說,適配器模式可以看作一種“補(bǔ)償模式”,用來補(bǔ)救設(shè)計(jì)上的缺陷。應(yīng)用這種模式算是“無奈之舉”,如果在設(shè)計(jì)初期,我們就能協(xié)調(diào)規(guī)避接口不兼容的問題,那這種模式就沒有應(yīng)用的機(jī)會(huì)了。