寫代碼常用到的設(shè)計(jì)模式

一,裝飾者模式

Paste_Image.png

總結(jié):裝飾者模式,就是對(duì)于父類A(Component),子類 B(ConcreteComponent)和C(Decorator)分別重新A中的方法,B中對(duì)方法進(jìn)行實(shí)現(xiàn),C及其子類可以調(diào)用B中實(shí)現(xiàn)的方法,也可以進(jìn)行方法的拓展

二,代理模式

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

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

最近正好在看,特來挖墳。
關(guān)于動(dòng)態(tài)代理設(shè)計(jì)模式很可能題主就在不知不覺中使用了,例如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();
   }
}

剛開始我會(huì)覺得SubjectProxy定義出來純屬多余,直接實(shí)例化實(shí)現(xiàn)類完成操作不就結(jié)了嗎?后來隨著業(yè)務(wù)龐大,你就會(huì)知道,實(shí)現(xiàn)proxy類對(duì)真實(shí)類的封裝對(duì)于粒度的控制有著重要的意義。但是靜態(tài)代理這個(gè)模式本身有個(gè)大問題,如果類方法數(shù)量越來越多的時(shí)候,代理類的代碼量是十分龐大的。所以引入動(dòng)態(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;

    //綁定委托對(duì)象,并返回代理類
    public Object bind(Object tar)
    {
        this.tar = tar;
        //綁定該類實(shí)現(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;
        //這里就可以進(jìn)行所謂的AOP編程了
        //在調(diào)用具體函數(shù)方法前,執(zhí)行功能處理
        result = method.invoke(tar,args);
        //在調(diào)用具體函數(shù)方法后,執(zhí)行功能處理
        return result;
    }
}


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

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

  1. Proxy類的代碼量被固定下來,不會(huì)因?yàn)闃I(yè)務(wù)的逐漸龐大而龐大;
  2. 可以實(shí)現(xiàn)AOP編程,實(shí)際上靜態(tài)代理也可以實(shí)現(xiàn),總的來說,AOP可以算作是代理模式的一個(gè)典型應(yīng)用;
  3. 解耦,通過參數(shù)就可以判斷真實(shí)類,不需要事先實(shí)例化,更加靈活多變。

三,工廠模式

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

四,原型模式

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

五,模板方法模式

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

    /*
     * 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()函數(shù)中調(diào)用了onDraw和dispatchDraw函數(shù),當(dāng)繼承View子類中,如果要重寫或者擴(kuò)展這個(gè)方法時(shí),整個(gè)方法流程和基本內(nèi)容不能夠修改,子類只能通過擴(kuò)展onDraw(Canvas canvas)和dispatchDraw(Canvas canvas)兩個(gè)函數(shù),使子類自己的View顯示效果和別的具體子類的不同。現(xiàn)在來看看繼承自View類的具體子類如何擴(kuò)展Draw()模板方法顯示自己的與眾不同:


Paste_Image.png

TextView類中重寫了OnDraw函數(shù),SurfaceView重寫了dispatchDraw()函數(shù),ViewGroup類重寫了dispatchDraw()函數(shù)。
根據(jù)模版方法中的方法,可以分為兩大類:模版方法(Template Method)和基本方法(Primitive Method)。其中我們這里的例子Draw()函數(shù)就是一個(gè)“模板方法”。
而基本方法又可以分為三種:抽象方法(Abstract Method)、具體方法(Concrete Method)和鉤子方法(Hook Method):
抽象方法:一個(gè)抽象方法由抽象類聲明,由具體子類實(shí)現(xiàn)。
具體方法:一個(gè)具體方法由抽象類聲明并實(shí)現(xiàn),而子類并不實(shí)現(xiàn)或置換。
鉤子方法:一個(gè)鉤子方法由抽象類聲明并實(shí)現(xiàn),而子類會(huì)加以擴(kuò)展。我們這里的onDraw()函數(shù)就是一個(gè)鉤子方法。

六,外觀模式

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

七,build模式

建造(Builder)模式是一種對(duì)象構(gòu)建的設(shè)計(jì)模式,它可以將復(fù)雜對(duì)象的建造過程抽象出來(抽象類別),使這個(gè)抽象過程的不同實(shí)現(xiàn)方法可以構(gòu)造出不同表現(xiàn)(屬性)的對(duì)象。
在沒有運(yùn)用構(gòu)造模式之前,我們可能會(huì)使用構(gòu)造方法還設(shè)置初始化對(duì)象時(shí)候的參數(shù),但是有了build模式,就可以通過build來進(jìn)行選擇性的傳參并實(shí)例化對(duì)象。例如,Android常用的第三方請(qǐng)求網(wǎng)絡(luò)庫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;
}

八 ,觀察者模式

觀察者模式的底層其實(shí)是回調(diào),Java中一般可以繼承Observable 和Observer來實(shí)現(xiàn)被觀察者和觀察者,在安卓中,更是運(yùn)用大量的觀察者模式,例如,BaseAdapter關(guān)聯(lián)了一個(gè)DataSetObservable對(duì)象,并實(shí)現(xiàn)registerDataSetObserver和unregisterDataSetObserver兩個(gè)方法實(shí)現(xiàn)注冊(cè)和撤銷Observer,方法notifyDataSetChanged間接調(diào)用Observer的實(shí)現(xiàn)者的onChange()方法,以達(dá)到通知數(shù)據(jù)改變的作用。使用ListView和BaseAdapter組合時(shí),當(dāng)BaseAdapter的item改變時(shí),我們經(jīng)常會(huì)調(diào)用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。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容