1:代理模式(Proxy)
情景:一個客戶不想或者不能夠直接引用一個對象,而代理對象可以在客戶端和目標對象之間起到中介的作用厢钧。
給某一個對象提供一個代理對象皿哨,并由代理對象控制對原對象的引用长酗。
靜態(tài)代理
可以做到在不修改目標對象的功能前提下,對目標對象調用铜涉,以及對目標功能擴展智玻。
缺點:因為代理對象需要與目標對象實現(xiàn)一樣的接口,所以會有很多代理類,類太多或者接口增加方法,目標對象與代理對象都要維護, 那么就有了動態(tài)代理芙代。
Android 靜態(tài)代理實例
插件化框架 dynamic-load-apk的核心思想可以總結為兩個字:代理吊奢。通過在 Manifest 中注冊代理組件Activity或者Service等,當啟動插件組件時首先啟動一個代理組件纹烹,然后通過這個代理組件來構建页滚、啟動插件組件對應的方法就OK了。
參考 :
Android 插件化框架 DynamicLoadApk 源碼解析
動態(tài)代理
代理對象,不需要實現(xiàn)接口,利用API的java.lang.reflect.Proxy類中方法newProxyInstances反射調用目標對象的方法铺呵,但是目標對象一定要實現(xiàn)接口,否則不能用動態(tài)代理裹驰。
代理對象
public class ProxyFactory {
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
public Object getProxyInstance(){
return Proxy.newProxyInstance(
target.getClass().getClassLoader()
, target.getClass().getInterfaces()
, new InvocationHandler() {
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
System.out.println("開始事務2");
//執(zhí)行目標對象方法
Object returnValue = method.invoke(target, objects);
return returnValue;
}
});
}
}
客戶實現(xiàn)
public class client {
public static void main(String[] args){
// 目標對象
AbstractObject abstractObject = new RealObject();
// 【原始的類型 class com.decoration.lib.proxy.sample2.RealObject】
System.out.println(abstractObject.getClass());
// 給目標對象,創(chuàng)建代理對象
AbstractObject proxyObject = (AbstractObject) new ProxyFactory(abstractObject).getProxyInstance();
// 【 class com.sun.proxy.$Proxy0 】 內(nèi)存中動態(tài)生成的代理對象
System.out.println(proxyObject.getClass());
// 執(zhí)行方法 【代理對象】
proxyObject.operation();
}
}
參考:
《Java的三種代理模式》
《Java設計模式——代理模式實現(xiàn)及原理》
2: 享元模式(Flyweight)
主要作用就是復用大對象(重量級對象)片挂,以節(jié)省內(nèi)存空間和對象創(chuàng)建時間幻林。
顧名思義:共享元對象。如果在一個系統(tǒng)中存在多個相同的對象宴卖,那么只需要共享一份對象的拷貝滋将,而不必為每一次使用創(chuàng)建新的對象。
public class FlyweightFactory {
private Map<Character,Flyweight> files = new HashMap<Character,Flyweight>();
public Flyweight factory(Character state){
//先從緩存中查找對象
Flyweight fly = files.get(state);
if(fly == null){
//如果對象不存在則創(chuàng)建一個新的Flyweight對象
fly = new ConcreteFlyweight(state);
//把這個新的Flyweight對象添加到緩存中
files.put(state, fly);
}
return fly;
}
}
優(yōu)點:大幅度地降低內(nèi)存中對象的數(shù)量症昏,節(jié)省內(nèi)存空間。
缺點:使得系統(tǒng)更加復雜父丰。為了使對象可以共享肝谭,需要將一些狀態(tài)外部化掘宪,這使得程序的邏輯復雜化。將享元對象的狀態(tài)外部化攘烛,而讀取外部狀態(tài)使得運行時間稍微變長魏滚。
應用場景:
1:享元模式由于其共享的特征,可以在任何“池”中操作坟漱,比如:線程池鼠次,數(shù)據(jù)庫連接池。
2:String類的設計也是享元模式(String對象是final類型芋齿,對象一旦創(chuàng)建就不可改變)
參考:
java設計模式---享元模式
《JAVA與模式》之享元模式
《Android源碼設計模式》--享元模式
3: 門面模式(外觀模式)
設立一個門面對象腥寇,使客戶訪問門面就可以了,不需要單獨調用里面不同的子系統(tǒng)模塊
初學者往往以為通過繼承一個門面類便可在子系統(tǒng)中加入新的行為觅捆,這是錯誤的赦役。門面模式的用意是為子系統(tǒng)提供一個集中化和簡化的溝通管道,而不能向子系統(tǒng)加入新的行為栅炒。
缺點:不符合開閉原則掂摔,如果要改東西很麻煩,繼承重寫都不合適赢赊。
參考: 《JAVA與模式》之門面模式
4:橋接模式(橋梁Bridge)
主要應對:由于實際的需要乙漓,某個類具有兩個或兩個以上的維度變化,如果只是用繼承將無法實現(xiàn)這種需要释移,或者使得設計變得相當臃腫叭披。
把抽象(abstraction)與行為實現(xiàn)(implementation)分離開來,從而可以保持各部分的獨立性以及應對它們的功能擴展秀鞭。
下面的AbstractComputer類就是橋接類趋观,AbstractComputer的具體實現(xiàn)是一個維度,其中的CpuAbility又是一個維度锋边,通過橋接類連接了兩個維度皱坛。
public abstract class AbstractComputer{
CpuAbility cpuAbility;
public AbstractComputer(CpuAbility cpuAbility){
this.cpuAbility=cpuAbility;
}
public abstract void checkPcAbility();
}
參考: 《JAVA與模式》之橋接模式
另外:
其中對象的適配器模式是結構型各種模式的起源: