寫代碼常用到的設計模式

一山卦,裝飾者模式

Paste_Image.png

總結:裝飾者模式哮独,就是對于父類A(Component)烟央,子類 B(ConcreteComponent)和C(Decorator)分別重新A中的方法,B中對方法進行實現(xiàn)瞒渠,C及其子類可以調用B中實現(xiàn)的方法良蒸,也可以進行方法的拓展

二,代理模式

可以查看這篇文章伍玖,http://blog.csdn.net/luanlouis/article/details/24589193

https://www.zhihu.com/question/20794107
作者:雨夜偷牛的人
鏈接:https://www.zhihu.com/question/20794107/answer/23330381
來源:知乎
著作權歸作者所有嫩痰,轉載請聯(lián)系作者獲得授權。

最近正好在看窍箍,特來挖墳串纺。
關于動態(tài)代理設計模式很可能題主就在不知不覺中使用了丽旅,例如Spring中的AOP,Struts2中的攔截器等造垛。

先來看靜態(tài)代理模式代碼:

package test;

public interface Subject   
{   
  public void doSomething();   
}


package test;

public class RealSubject implements Subject   
{   
  public void doSomething()   
  {   
    System.out.println( "call doSomething()" );   
  }   
}  


package test;

public class SubjectProxy implements Subject
{
  Subject subimpl = new RealSubject();
  public void doSomething()
  {
     subimpl.doSomething();
  }
}


package test;

public class TestProxy 
{
   public static void main(String args[])
   {
       Subject sub = new SubjectProxy();
       sub.doSomething();
   }
}

剛開始我會覺得SubjectProxy定義出來純屬多余,直接實例化實現(xiàn)類完成操作不就結了嗎晰搀?后來隨著業(yè)務龐大五辽,你就會知道,實現(xiàn)proxy類對真實類的封裝對于粒度的控制有著重要的意義外恕。但是靜態(tài)代理這個模式本身有個大問題杆逗,如果類方法數量越來越多的時候,代理類的代碼量是十分龐大的鳞疲。所以引入動態(tài)代理來解決此類問題罪郊。

先看代碼:

package test;

public interface Subject   
{   
  public void doSomething();   
}


package test;

public class RealSubject implements Subject   
{   
  public void doSomething()   
  {   
    System.out.println( "call doSomething()" );   
  }   
}  


package test;

import java.lang.reflect.InvocationHandler;  
import java.lang.reflect.Method;  
import java.lang.reflect.Proxy;  

public class ProxyHandler implements InvocationHandler
{
    private Object tar;

    //綁定委托對象,并返回代理類
    public Object bind(Object tar)
    {
        this.tar = tar;
        //綁定該類實現(xiàn)的所有接口尚洽,取得代理類 
        return Proxy.newProxyInstance(tar.getClass().getClassLoader(),
                                      tar.getClass().getInterfaces(),
                                      this);
    }    

    public Object invoke(Object proxy , Method method , Object[] args)throws Throwable
    {
        Object result = null;
        //這里就可以進行所謂的AOP編程了
        //在調用具體函數方法前悔橄,執(zhí)行功能處理
        result = method.invoke(tar,args);
        //在調用具體函數方法后,執(zhí)行功能處理
        return result;
    }
}


public class TestProxy
{
    public static void main(String args[])
    {
           ProxyHandler proxy = new ProxyHandler();
           //綁定該類實現(xiàn)的所有接口
           Subject sub = (Subject) proxy.bind(new RealSubject());
           sub.doSomething();
    }
}

看完代碼腺毫,現(xiàn)在我來回答癣疟,動態(tài)代理的作用是什么:

  1. Proxy類的代碼量被固定下來,不會因為業(yè)務的逐漸龐大而龐大潮酒;
  2. 可以實現(xiàn)AOP編程睛挚,實際上靜態(tài)代理也可以實現(xiàn),總的來說急黎,AOP可以算作是代理模式的一個典型應用扎狱;
  3. 解耦,通過參數就可以判斷真實類勃教,不需要事先實例化淤击,更加靈活多變。

三故源,工廠模式

http://blog.csdn.net/jason0539/article/details/23020989
工廠模式分為簡單工廠模式遭贸,工廠方法模式和抽象工廠模式
簡單工廠就是利用factory類創(chuàng)建對象,
抽象工廠是用多個factory創(chuàng)建對象心软,

四壕吹,原型模式

http://blog.csdn.net/sbsujjbcy/article/details/49302717

五,模板方法模式

在Android源碼中删铃,View中的Draw()方法就是一個“模板方法”耳贬。它定義了一系列“Draw”過程,主要包括這幾個步驟(截取自源代碼):

    /*
     * Draw traversal performs several drawing steps which must be executed
     * in the appropriate order:
     *
     *      1. Draw the background
     *      2. If necessary, save the canvas' layers to prepare for fading
     *      3. Draw view's content
     *      4. Draw children
     *      5. If necessary, draw the fading edges and restore layers
     *      6. Draw decorations (scrollbars for instance)
     */

在view類的draw()函數中調用了onDraw和dispatchDraw函數猎唁,當繼承View子類中咒劲,如果要重寫或者擴展這個方法時,整個方法流程和基本內容不能夠修改,子類只能通過擴展onDraw(Canvas canvas)和dispatchDraw(Canvas canvas)兩個函數腐魂,使子類自己的View顯示效果和別的具體子類的不同≌寿耍現(xiàn)在來看看繼承自View類的具體子類如何擴展Draw()模板方法顯示自己的與眾不同:


Paste_Image.png

TextView類中重寫了OnDraw函數,SurfaceView重寫了dispatchDraw()函數蛔屹,ViewGroup類重寫了dispatchDraw()函數削樊。
根據模版方法中的方法,可以分為兩大類:模版方法(Template Method)和基本方法(Primitive Method)兔毒。其中我們這里的例子Draw()函數就是一個“模板方法”漫贞。
而基本方法又可以分為三種:抽象方法(Abstract Method)、具體方法(Concrete Method)和鉤子方法(Hook Method):
抽象方法:一個抽象方法由抽象類聲明育叁,由具體子類實現(xiàn)迅脐。
具體方法:一個具體方法由抽象類聲明并實現(xiàn),而子類并不實現(xiàn)或置換豪嗽。
鉤子方法:一個鉤子方法由抽象類聲明并實現(xiàn)谴蔑,而子類會加以擴展。我們這里的onDraw()函數就是一個鉤子方法龟梦。

六树碱,外觀模式

就是多了層封裝,SDK常用到

七变秦,build模式

建造(Builder)模式是一種對象構建的設計模式成榜,它可以將復雜對象的建造過程抽象出來(抽象類別),使這個抽象過程的不同實現(xiàn)方法可以構造出不同表現(xiàn)(屬性)的對象蹦玫。
在沒有運用構造模式之前赎婚,我們可能會使用構造方法還設置初始化對象時候的參數,但是有了build模式樱溉,就可以通過build來進行選擇性的傳參并實例化對象挣输。例如,Android常用的第三方請求網絡庫okhttp福贞,

OkHttpClient client = new OkHttpClient.Builder()
 .connectTimeout(15, TimeUnit.SECONDS)
 .readTimeout(15, TimeUnit.SECONDS)
 .build();

OkHttpClient類中該方法如下撩嚼,

public Builder() {
 dispatcher = new Dispatcher();
 protocols = DEFAULT_PROTOCOLS;
 connectionSpecs = DEFAULT_CONNECTION_SPECS;
 proxySelector = ProxySelector.getDefault();
 cookieJar = CookieJar.NO_COOKIES;
 socketFactory = SocketFactory.getDefault();
 hostnameVerifier = OkHostnameVerifier.INSTANCE;
 certificatePinner = CertificatePinner.DEFAULT;
 proxyAuthenticator = Authenticator.NONE;
 authenticator = Authenticator.NONE;
 connectionPool = new ConnectionPool();
 dns = Dns.SYSTEM;
 followSslRedirects = true;
 followRedirects = true;
 retryOnConnectionFailure = true;
 connectTimeout = 10_000;
 readTimeout = 10_000;
 writeTimeout = 10_000;
}

八 ,觀察者模式

觀察者模式的底層其實是回調挖帘,Java中一般可以繼承Observable 和Observer來實現(xiàn)被觀察者和觀察者完丽,在安卓中,更是運用大量的觀察者模式拇舀,例如逻族,BaseAdapter關聯(lián)了一個DataSetObservable對象,并實現(xiàn)registerDataSetObserver和unregisterDataSetObserver兩個方法實現(xiàn)注冊和撤銷Observer骄崩,方法notifyDataSetChanged間接調用Observer的實現(xiàn)者的onChange()方法聘鳞,以達到通知數據改變的作用薄辅。使用ListView和BaseAdapter組合時,當BaseAdapter的item改變時抠璃,我們經常會調用notifyDataSetChanged()站楚,通知Listview刷新。

public abstract class DataSetObserver {
 /**
 * This method is called when the entire data set has changed,
 * most likely through a call to {@link Cursor#requery()} on a {@link Cursor}.
 */
 public void onChanged() {
 // Do nothing
 }

 /**
 * This method is called when the entire data becomes invalid,
 * most likely through a call to {@link Cursor#deactivate()} or {@link Cursor#close()} on a
 * {@link Cursor}.
 */
 public void onInvalidated() {
 // Do nothing
 }
}
public abstract class Observable<T> {
 /**
 * The list of observers. An observer can be in the list at most
 * once and will never be null.
 */
 protected final ArrayList<T> mObservers = new ArrayList<T>();

 /**
 * Adds an observer to the list. The observer cannot be null and it must not already
 * be registered.
 * @param observer the observer to register
 * @throws IllegalArgumentException the observer is null
 * @throws IllegalStateException the observer is already registered
 */
 public void registerObserver(T observer) {
 if (observer == null) {
 throw new IllegalArgumentException("The observer is null.");
 }
 synchronized(mObservers) {
 if (mObservers.contains(observer)) {
 throw new IllegalStateException("Observer " + observer + " is already registered.");
 }
 mObservers.add(observer);
 }
 }

 /**
 * Removes a previously registered observer. The observer must not be null and it
 * must already have been registered.
 * @param observer the observer to unregister
 * @throws IllegalArgumentException the observer is null
 * @throws IllegalStateException the observer is not yet registered
 */
 public void unregisterObserver(T observer) {
 if (observer == null) {
 throw new IllegalArgumentException("The observer is null.");
 }
 synchronized(mObservers) {
 int index = mObservers.indexOf(observer);
 if (index == -1) {
 throw new IllegalStateException("Observer " + observer + " was not registered.");
 }
 mObservers.remove(index);
 }
 }

 /**
 * Remove all registered observers.
 */
 public void unregisterAll() {
 synchronized(mObservers) {
 mObservers.clear();
 }
 }
}

可以看出搏嗡,觀察者并不一定要繼承JDK中的Observable 和Observer窿春。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市彻况,隨后出現(xiàn)的幾起案子谁尸,更是在濱河造成了極大的恐慌舅踪,老刑警劉巖纽甘,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異抽碌,居然都是意外死亡悍赢,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進店門货徙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來左权,“玉大人,你說我怎么就攤上這事痴颊∩统伲” “怎么了?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵蠢棱,是天一觀的道長锌杀。 經常有香客問我,道長泻仙,這世上最難降的妖魔是什么糕再? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮玉转,結果婚禮上突想,老公的妹妹穿的比我還像新娘。我一直安慰自己究抓,他們只是感情好猾担,可當我...
    茶點故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著刺下,像睡著了一般垒探。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上怠李,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天圾叼,我揣著相機與錄音蛤克,去河邊找鬼。 笑死夷蚊,一個胖子當著我的面吹牛构挤,可吹牛的內容都是我干的。 我是一名探鬼主播惕鼓,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼筋现,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了箱歧?” 一聲冷哼從身側響起矾飞,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎呀邢,沒想到半個月后洒沦,有當地人在樹林里發(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡价淌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年申眼,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蝉衣。...
    茶點故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡括尸,死狀恐怖,靈堂內的尸體忽然破棺而出病毡,到底是詐尸還是另有隱情濒翻,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布啦膜,位于F島的核電站有送,受9級特大地震影響,放射性物質發(fā)生泄漏功戚。R本人自食惡果不足惜娶眷,卻給世界環(huán)境...
    茶點故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望啸臀。 院中可真熱鬧届宠,春花似錦、人聲如沸乘粒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽灯萍。三九已至轧铁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間旦棉,已是汗流浹背齿风。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工药薯, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人救斑。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓童本,卻偏偏與公主長得像,于是被迫代替她去往敵國和親脸候。 傳聞我的和親對象是個殘疾皇子穷娱,可洞房花燭夜當晚...
    茶點故事閱讀 45,512評論 2 359

推薦閱讀更多精彩內容