Android中所涉及的常用設計模式

1、單例模式

概念:Ensure a class has only one instance, and provide a global point of access to it.

動態確保某一個類只有一個實例,而且自行實例化并向整個系統提供這個實例。

優點:

1.1、由于單例模式在內存中只有一個實例,減少了內存開銷。對于那些耗內存的類,只實例化一次,大大提高性能,尤其是移動開發中。

1.2、單例模式可以避免對資源的多重占用,例如一個寫文件時,由于只有一個實例存在內存中,避免對同一個資源文件的同時寫操作。

1.3、單例模式可以在系統設置全局的訪問點,優化和共享資源訪問。

public class Singleton {
private volatile static Singleton instance = null;

private Singleton(){  
}  

public static Singleton getInstance() {  
    if (instance == null) {  
        synchronized (Singleton.class) {  
            if (instance == null) {  
                instance = new Singleton();  
            }  
        }  
    }  
    return instance;  
}  

}</code></pre>

構造函數私有化,定 義靜態函數獲

得實例就不多說了,這里著重說一下volatile:

volatile本質是在告訴jvm當前變量在寄存器中的值是不確定的,需要從內存中讀取,synchronized則是鎖定當前變量,只有當前線程可以訪問該變量,其他線程被阻塞住.(首先我們要先意識到有這樣的現象,編譯器為了加快程序運行的速度,對一些變量的寫操作會先在寄存器或者是CPU緩存上進行,最后才寫入內存.

而在這個過程,變量的新值對其他線程是不可見的.而volatile的作用就是使它修飾的變量的讀寫操作都必須在內存中進行!)

synchronized

同步塊大家都比較熟悉,通過 synchronized 關鍵字來實現,所有加上synchronized 和 塊語句,在多線程訪問的時候,同一時刻只能有一個線程能夠用

synchronized 修飾的方法 或者 代碼塊。

volatile

用volatile修飾的變量,線程在每次使用變量的時候,都會讀取變量修改后的最的值。volatile很容易被誤用,用來進行原子性操作。

再就是這個雙重判斷null :

這是因為如果線程A進入了該代碼,線程B 在等待,這是A線程創建完一個實例出來后,線程B 獲得鎖進入同步代碼,實例已經存在,木有必要再創建一個,所以雙重判斷有必要。

Android中 用到的地方很多,比如Android-Universal-Image-Loader中的單例,EventBus中的單例

最后給出一個管理我們activity的類,可以作為一個簡單工具類

public class ActivityManager {

private static volatile ActivityManager instance;  
private Stack<Activity> mActivityStack = new Stack<Activity>();  

private ActivityManager(){  

}  

public static ActivityManager getInstance(){  
    if (instance == null) {  
    synchronized (ActivityManager.class) {  
        if (instance == null) {  
            instance = new ActivityManager();  
        }  
    }  
    return instance;  
}  

public void addActicity(Activity act){  
    mActivityStack.push(act);  
}  

public void removeActivity(Activity act){  
    mActivityStack.remove(act);  
}  

public void killMyProcess(){  
    int nCount = mActivityStack.size();  
    for (int i = nCount - 1; i >= 0; i--) {  
        Activity activity = mActivityStack.get(i);  
        activity.finish();  
    }  

    mActivityStack.clear();  
    android.os.Process.killProcess(android.os.Process.myPid());  
}  

}</code></pre>

單例模式在Android源碼中的應用:

在Android源碼中,使用到單例模式的例子很多,如:

InputMethodManager類

public final class InputMethodManager {
    static final boolean DEBUG = false;
    static final String TAG = "InputMethodManager";

static final Object mInstanceSync = new Object();
static InputMethodManager mInstance;

final IInputMethodManager mService;
final Looper mMainLooper;</code></pre> 

創建唯一的實例static InputMethodManager mInstance;

/**
     * Retrieve the global InputMethodManager instance, creating it if it
     * doesn't already exist.
     * @hide
     */
    static public InputMethodManager getInstance(Context context) {
        return getInstance(context.getMainLooper());
    }

    /**
     * Internally, the input method manager can't be context-dependent, so
     * we have this here for the places that need it.
     * @hide
     */
    static public InputMethodManager getInstance(Looper mainLooper) {
        synchronized (mInstanceSync) {
            if (mInstance != null) {
                return mInstance;
            }
            IBinder b = ServiceManager.getService(Context.INPUT_METHOD_SERVICE);
            IInputMethodManager service = IInputMethodManager.Stub.asInterface(b);
            mInstance = new InputMethodManager(service, mainLooper);
        }
        return mInstance;
    }

防止多線程同時創建實例:

synchronized  (mInstanceSync) {
             if (mInstance !=  null ) {
                 return  mInstance;
            }
當沒有創建實例對象時,調用mInstance =  new  InputMethodManager(service, mainLooper);
其中類構造函數如下所示:

InputMethodManager(IInputMethodManager service, Looper looper) {
        mService = service;
        mMainLooper = looper;
        mH = new H(looper);
        mIInputContext = new ControlledInputConnectionWrapper(looper,
                mDummyInputConnection);

        if (mInstance == null) {
            mInstance = this;
        }
    }

2、 建造者模式( Builder 模式 )

定義:將一個復雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示

概念就是比較抽象的,讓大家很難理解的,如果簡單從這個一個概念就搞懂了這個模式的話,那就不用費力的去查資料整理后邊的東西了。

這里我們通過一個例子來引出Build模式。假設有一個Person類,他的一些屬性可以為null,可以通過這個類來構架一大批人

public class Person {  
    private String name;  
    private int age;  
    private double height;  
    private double weight;  

    public String getName() {  
        return name;  
    }  

    public void setName(String name) {  
        this.name = name;  
    }  

    public int getAge() {  
        return age;  
    }  

    public void setAge(int age) {  
        this.age = age;  
    }  

    public double getHeight() {  
        return height;  
    }  

    public void setHeight(double height) {  
        this.height = height;  
    }  

    public double getWeight() {  
        return weight;  
    }  

    public void setWeight(double weight) {  
        this.weight = weight;  
    }  
}

然后為了方便,你可能會寫這么一個構造函數來傳屬性

public Person(String name, int age, double height, double weight) {  
    this.name = name;  
    this.age = age;  
    this.height = height;  
    this.weight = weight;  
}

或者為了更方便還會寫一個空的構造函數

public Person() {  
}

有時候還會比較懶,只傳入某些參數,又會來寫這些構造函數

public Person(String name) {  
    this.name = name;  
}  

public Person(String name, int age) {  
    this.name = name;  
    this.age = age;  
}  

public Person(String name, int age, double height) {  
    this.name = name;  
    this.age = age;  
    this.height = height;  
}

于是就可以來創建各種需要的類

Person p1=new Person();  
Person p2=new Person("張三");  
Person p3=new Person("李四",18);  
Person p4=new Person("王二",21,180);  
Person p5=new Person("麻子",16,170,65.4);

其實這種寫法的壞處在你寫的過程中想摔鍵盤的時候就該想到了,既然就是一個創建對象的過程,怎么這么繁瑣,并且構造函數參數過多,其他人創建對象的時候怎么知道各個參數代表什么意思呢,這個時候我們為了代碼的可讀性,就可以用一下Builder模式了

給Person類添加一個靜態Builder類,然后修改Person的構造函數,如下:

public class Person {  
    private String name;  
    private int age;  
    private double height;  
    private double weight;  

    privatePerson(Builder builder) {  
        this.name=builder.name;  
        this.age=builder.age;  
        this.height=builder.height;  
        this.weight=builder.weight;  
    }  
    public String getName() {  
        return name;  
    }  

    public void setName(String name) {  
        this.name = name;  
    }  

    public int getAge() {  
        return age;  
    }  

    public void setAge(int age) {  
        this.age = age;  
    }  

    public double getHeight() {  
        return height;  
    }  

    public void setHeight(double height) {  
        this.height = height;  
    }  

    public double getWeight() {  
        return weight;  
    }  

    public void setWeight(double weight) {  
        this.weight = weight;  
    }  

    static class Builder{  
        private String name;  
        private int age;  
        private double height;  
        private double weight;  
        public Builder name(String name){  
            this.name=name;  
            return this;  
        }  
        public Builder age(int age){  
            this.age=age;  
            return this;  
        }  
        public Builder height(double height){  
            this.height=height;  
            return this;  
        }  

        public Builder weight(double weight){  
            this.weight=weight;  
            return this;  
        }  

        public Person build(){  
            return new Person(this);  
        }  
    }  
}

從上邊代碼我們可以看到我們在Builder類中定義了一份跟Person類一樣的屬性,通過一系列的成員函數進行賦值,但是返回的都是this,最后提供了一個build函數來創建person對象,對應的在Person的構造函數中,傳入了 Builder

對象,然后依次對自己的成員變量進行賦值。此外,Builder的成員函數返回的都是this的另一個作用就是讓他支持鏈式調用,使代碼可讀性大大增強

于是我們就可以這樣創建Person對象

Person.Builder builder=new Person.Builder();  
Person person=builder  
        .name("張三")  
        .age(18)  
        .height(178.5)  
        .weight(67.4)  
        .build();

是不是有那么點感覺了呢

Android中大量地方運用到了Builder模式,比如常見的對話框創建

AlertDialog.Builder builder=new AlertDialog.Builder(this);  
AlertDialog dialog=builder.setTitle("對話框")  
        .setIcon(android.R.drawable.ic_dialog)  
        .setView(R.layout.custom_view)  
        .setPositiveButton(R.string.positive, new DialogInterface.OnClickListener() {  
            @Override  
            public void onClick(DialogInterface dialog, int which) {  

            }  
        })  
        .setNegativeButton(R.string.negative, new DialogInterface.OnClickListener() {  
            @Override  
            public void onClick(DialogInterface dialog, int which) {  

            }  
        })  
        .create();  
dialog.show();

其實在java中StringBuilder 和StringBuffer都用到了Builder模式,只不過是稍微簡單一點了

Gson中的GsonBuilder

GsonBuilder builder=new GsonBuilder();  
Gson gson=builder.setPrettyPrinting()  
        .disableHtmlEscaping()  
        .generateNonExecutableJson()  
        .serializeNulls()  
        .create();

網絡框架OKHttp

Request.Builder builder=new Request.Builder();  
Request request=builder.addHeader("","")  
    .url("")  
    .post(body)  
    .build();

可見大量框架運用了Builder 設計模式,總結一下吧:

定義一個靜態內部類Builder,內部成員變量跟外部一樣

Builder通過一系列方法給成員變量賦值,并返回當前對象(this)

Builder類內部提供一個build方法方法或者create方法用于創建對應的外部類,該方法內部調用了外部類的一個私有化構造方法,該構造方法的參數就是內部類Builder

外部類提供一個私有化的構造方法供內部類調用,在該構造函數中完成成員變量的賦值

3、 觀察者模式

定義:Define a one-to-many dependency between objects so that when one object changes state, all its dependents aer notified and updated automatically.
定義對象間一種一對多的依賴關系,使得當一個對象改變狀態,則所有依賴于它的對象都會得到通知并被自動更新。

主要包括四個部分:

1. Subject被觀察者。是一個接口或者是抽象類,定義被觀察者必須實現的職責,它必須能偶動態地增加、取消觀察者,管理觀察者并通知觀察者。

2. Observer觀察者。觀察者接收到消息后,即進行update更新操作,對接收到的信息進行處理。

3. ConcreteSubject具體的被觀察者。定義被觀察者自己的業務邏輯,同時定義對哪些事件進行通知。

4. ConcreteObserver具體觀察者。每個觀察者在接收到信息后處理的方式不同,各個觀察者有自己的處理邏輯。

這個好像還好理解那么一點點,不過還是先來講個情景,

天氣預報的短信服務,一旦付費訂閱,每次天氣更新都會向你及時發送

其實就是我們無需每時每刻關注我們感興趣的東西,我們只需要訂閱它即可,一旦我們訂閱的事務有變化了,被訂閱的事務就會即時的通知我們

我們來看一下觀察者模式的組成:

  • 觀察者,我們稱它為Observer,有時候我們也稱它為訂閱者,即Subscriber
  • 被觀察者,我們稱它為Observable,即可以被觀察的東西,有時候還會稱之為主題,即Subject

至于觀察者模式的具體實現,java里為我們提供了Observable類和Observer接口供我們快速實現該模式,但是這里為了加深印象,不用這個兩個類

我們來模擬上邊的場景,先定義一個Weather的類

public class Weather {  
    private String description;  

    public Weather(String description) {  
        this.description = description;  
    }  

    public String getDescription() {  
        return description;  
    }  

    public void setDescription(String description) {  
        this.description = description;  
    }  

    @Override  
    public String toString() {  
        return "Weather{" +  
                "description='" + description + '\'' +  
                '}';  
    }  
}

然后定義我們的被觀察著,我們希望它能夠通用,所以定義成泛型,內部應該暴露出register和unRegister供觀察者訂閱和取消訂閱,至于觀察者的保存,我們用ArrayList即可,另外,當主題發生變化的時候,需要通知觀察者來做出響應,還需要一個notifyObservers方法,具體實現如下:

public class Observable<T> {  
    List<Observer<T>> mObservers = new ArrayList<Observer<T>>();  

    public void register(Observer<T> observer) {  
        if (observer == null) {  
            throw new NullPointerException("observer == null");  
        }  
        synchronized (this) {  
            if (!mObservers.contains(observer))  
                mObservers.add(observer);  
        }  
    }  

    public synchronized void unregister(Observer<T> observer) {  
        mObservers.remove(observer);  
    }  

    public void notifyObservers(T data) {  
        for (Observer<T> observer : mObservers) {  
            observer.onUpdate(this, data);  
        }  
    }  

}

而我們的觀察者只需要實現一個觀察者的接口Observer,該接口也是泛型的

public interface Observer<T> {  
    void onUpdate(Observable<T> observable,T data);  
}

一旦訂閱的主題發生了變化,就會調用該接口

用一下,我們定義一個天氣變化的主題,也就是被觀察者,再定義兩個觀察者來觀察天氣的變化,一旦變化了就打印出天氣的情況,注意,一定要用register方法來注冊,否則觀察者收不到變化的信息,而一旦不感興趣,就可以調用unregister方法

public class Main {  
    public static void main(String [] args){  
        Observable<Weather> observable=new Observable<Weather>();  
        Observer<Weather> observer1=new Observer<Weather>() {  
            @Override  
            public void onUpdate(Observable<Weather> observable, Weather data) {  
                System.out.println("觀察者1:"+data.toString());  
            }  
        };  
        Observer<Weather> observer2=new Observer<Weather>() {  
            @Override  
            public void onUpdate(Observable<Weather> observable, Weather data) {  
                System.out.println("觀察者2:"+data.toString());  
            }  
        };  

        observable.register(observer1);  
        observable.register(observer2);  


        Weather weather=new Weather("晴轉多云");  
        observable.notifyObservers(weather);  

        Weather weather1=new Weather("多云轉陰");  
        observable.notifyObservers(weather1);  

        observable.unregister(observer1);  

        Weather weather2=new Weather("臺風");  
        observable.notifyObservers(weather2);  

    }  
}

輸出也沒有問題

觀察者1:Weather{description=’晴轉多云’}

觀察者2:Weather{description=’晴轉多云’}

觀察者1:Weather{description=’多云轉陰’}

觀察者2:Weather{description=’多云轉陰’}

觀察者2:Weather{description=’臺風’}

好,我們來看一下在Android中的應用,從最簡單的開始,Button的點擊事件

Button btn=new Button(this);  
btn.setOnClickListener(new View.OnClickListener() {  
    @Override  
    public void onClick(View v) {  
        Log.e("TAG","click");  
    }  
});

另外廣播機制,本質也是觀察者模式

調用registerReceiver方法注冊廣播,調用unregisterReceiver方法取消注冊,之后使用sendBroadcast發送廣播,之后注冊的廣播會受到對應的廣播信息,這就是典型的觀察者模式

開源框架EventBus也是基于觀察者模式的,

觀察者模式的注冊,取消,發送事件三個典型方法都有

EventBus.getDefault().register(Object subscriber);  
EventBus.getDefault().unregister(Object subscriber);  

EventBus.getDefault().post(Object event);

4 、策略模式

定義:策略模式定義了一系列算法,并將每一個算法封裝起來,而且使他們可以相互替換,策略模式讓算法獨立于使用的客戶而獨立改變

最常見的就是關于出行旅游的策略模式,出行方式有很多種,自行車,汽車,飛機,火車等,如果不使用任何模式,代碼是這樣子的

public class TravelStrategy {  
    enum Strategy{  
        WALK,PLANE,SUBWAY  
    }  
    private Strategy strategy;  
    public TravelStrategy(Strategy strategy){  
        this.strategy=strategy;  
    }  

    public void travel(){  
        if(strategy==Strategy.WALK){  
            print("walk");  
        }else if(strategy==Strategy.PLANE){  
            print("plane");  
        }else if(strategy==Strategy.SUBWAY){  
            print("subway");  
        }  
    }  

    public void print(String str){  
        System.out.println("出行旅游的方式為:"+str);  
    }  

    public static void main(String[] args) {  
        TravelStrategy walk=new TravelStrategy(Strategy.WALK);  
        walk.travel();  

        TravelStrategy plane=new TravelStrategy(Strategy.PLANE);  
        plane.travel();  

        TravelStrategy subway=new TravelStrategy(Strategy.SUBWAY);  
        subway.travel();  
    }  
}

很明顯,如果需要增加出行方式就需要在增加新的else if語句,這違反了面向對象的原則之一,對修改封裝(開放封閉原則)

題外話:面向對象的三大特征:封裝,繼承和多態

五大基本原則:單一職責原則(接口隔離原則),開放封閉原則,Liskov替換原則,依賴倒置原則,良性依賴原則

好,回歸主題,如何用策略模式來解決這個問題

首先,定義一個策略的接口

public interface Strategy {  
    void travel();  
}

然后根據不同的出行方法來實現該接口

public class WalkStrategy implements Strategy{  

    @Override  
    public void travel() {  
        System.out.println("walk");  
    }  

}
public class PlaneStrategy implements Strategy{  

    @Override  
    public void travel() {  
        System.out.println("plane");  
    }  

}
public class SubwayStrategy implements Strategy{  

    @Override  
    public void travel() {  
        System.out.println("subway");  
    }  

}

此外還需要一個包裝策略的類,來調用策略中的接口

public class TravelContext {  
    Strategy strategy;  

    public Strategy getStrategy() {  
        return strategy;  
    }  

    public void setStrategy(Strategy strategy) {  
        this.strategy = strategy;  
    }  

    public void travel() {  
        if (strategy != null) {  
            strategy.travel();  
        }  
    }  
}

測試一下代碼:

public class Main {  
    public static void main(String[] args) {  
        TravelContext travelContext=new TravelContext();  
        travelContext.setStrategy(new PlaneStrategy());  
        travelContext.travel();  
        travelContext.setStrategy(new WalkStrategy());  
        travelContext.travel();  
        travelContext.setStrategy(new SubwayStrategy());  
        travelContext.travel();  
    }  
}

以后如果再增加什么別的出行方式,就再繼承策略接口即可,完全不需要修改現有的類

策略模式優缺點

定義一系列算法:策略模式的功能就是定義一系列算法,實現讓這些算法可以相互替換。所以會為這一系列算法定義公共的接口,以約束一系列算法要實現的功能。如果這一系列算法具有公共功能,可以把策略接口實現成為抽象類,把這些公共功能實現到父類里面,對于這個問題,前面講了三種處理方法,這里就不羅嗦了。

避免多重條件語句:根據前面的示例會發現,策略模式的一系列策略算法是平等的,可以互換的,寫在一起就是通過if-else結構來組織,如果此時具體的算法實現里面又有條件語句,就構成了多重條件語句,使用策略模式能避免這樣的多重條件語句。

更好的擴展性:在策略模式中擴展新的策略實現非常容易,只要增加新的策略實現類,然后在選擇使用策略的地方選擇使用這個新的策略實現就好了。

客戶必須了解每種策略的不同:策略模式也有缺點,比如讓客戶端來選擇具體使用哪一個策略,這就可能會讓客戶需要了解所有的策略,還要了解各種策略的功能和不同,這樣才能做出正確的選擇,而且這樣也暴露了策略的具體實現。

增加了對象數目:由于策略模式把每個具體的策略實現都單獨封裝成為類,如果備選的策略很多的話,那么對象的數目就會很可觀。

只適合扁平的算法結構:策略模式的一系列算法地位是平等的,是可以相互替換的,事實上構成了一個扁平的算法結構,也就是在一個策略接口下,有多個平等的策略算法,就相當于兄弟算法。而且在運行時刻只有一個算法被使用,這就限制了算法使用的層級,使用的時候不能嵌套使用。

Android中的應用

下面說說在Android里面的應用。在Android里面策略模式的其中一個典型應用就是Adapter,在我們平時使用的時候,一般情況下我們可能繼承BaseAdapter,然后實現不同的View返回,GetView里面實現不同的算法。外部使用的時候也可以根據不同的數據源,切換不同的Adapter。

5、原型模式

定義:用原型實例指定創建對象的種類,并通過拷貝這些原型創建新的對象。

public class Person{  
    private String name;  
    private int age;  
    private double height;  
    private double weight;  

    public Person(){  

    }  

    public String getName() {  
        return name;  
    }  

    public void setName(String name) {  
        this.name = name;  
    }  

    public int getAge() {  
        return age;  
    }  

    public void setAge(int age) {  
        this.age = age;  
    }  

    public double getHeight() {  
        return height;  
    }  

    public void setHeight(double height) {  
        this.height = height;  
    }  

    public double getWeight() {  
        return weight;  
    }  

    public void setWeight(double weight) {  
        this.weight = weight;  
    }  

    @Override  
    public String toString() {  
        return "Person{" +  
                "name='" + name + '\'' +  
                ", age=" + age +  
                ", height=" + height +  
                ", weight=" + weight +  
                '}';  
    }  
}

要實現原型模式,按照以下步驟來:

1,實現一個Cloneable接口

public class Person implements Cloneable{  

}

重寫Object的clone方法,在此方法中實現拷貝邏輯

@Override  
public Object clone(){  
    Person person=null;  
    try {  
        person=(Person)super.clone();  
        person.name=this.name;  
        person.weight=this.weight;  
        person.height=this.height;  
        person.age=this.age;  
    } catch (CloneNotSupportedException e) {  
        e.printStackTrace();  
    }  
    return person;  
}

測試一下:

public class Main {  
    public static void main(String [] args){  
        Person p=new Person();  
        p.setAge(18);  
        p.setName("張三");  
        p.setHeight(178);  
        p.setWeight(65);  
        System.out.println(p);  

        Person p1= (Person) p.clone();  
        System.out.println(p1);  

        p1.setName("李四");  
        System.out.println(p);  
        System.out.println(p1);  
    }  
}

輸出結果如下:

Person{name=’張三’, age=18, height=178.0, weight=65.0}

Person{name=’張三’, age=18, height=178.0, weight=65.0}

Person{name=’張三’, age=18, height=178.0, weight=65.0}

Person{name=’李四’, age=18, height=178.0, weight=65.0}

試想一下,兩個不同的人,除了姓名不一樣,其他三個屬性都一樣,用原型模式進行拷貝就會顯得異常簡單,這也是原型模式的應用場景之一

假設Person類還有一個屬性叫興趣集合,是一個List集合,就醬紫:

private ArrayList<String> hobbies=new ArrayList<String>();  

public ArrayList<String> getHobbies() {  
    return hobbies;  
}  

public void setHobbies(ArrayList<String> hobbies) {  
    this.hobbies = hobbies;  
}

在進行拷貝的時候就要注意了,如果還是跟之前的一樣操作,就會發現其實兩個不同的人的興趣集合的是指向同一個引用,我們對其中一個人的這個集合屬性進行操作 ,另一個人的這個屬性也會相應的變化,其實導致這個問題的本質原因是我們只進行了淺拷貝,也就是指拷貝了引用,最終兩個對象指向的引用是同一個,一個發生變化,另一個也會發生拜變化。顯然解決方法就是使用深拷貝

@Override  
public Object clone(){  
    Person person=null;  
    try {  
        person=(Person)super.clone();  
        person.name=this.name;  
        person.weight=this.weight;  
        person.height=this.height;  
        person.age=this.age;  

        person.hobbies=(ArrayList<String>)this.hobbies.clone();  
    } catch (CloneNotSupportedException e) {  
        e.printStackTrace();  
    }  
    return person;  
}

不再是直接引用,而是拷貝了一份,

其實有的時候我們看到的原型模式更多的是另一種寫法:在clone函數里調用構造函數,構造函數里傳入的參數是該類對象,然后在函數中完成邏輯拷貝

@Override  
public Object clone(){  
    return new Person(this);  
}
public Person(Person person){  
    this.name=person.name;  
    this.weight=person.weight;  
    this.height=person.height;  
    this.age=person.age;  
    this.hobbies= new ArrayList<String>(hobbies);  
}

其實都差不多,只是寫法不一樣而已

現在 來看看Android中的原型模式:

先看Bundle類,

public Object clone() {  
    return new Bundle(this);  
}   
public Bundle(Bundle b) {  
    super(b);  

    mHasFds = b.mHasFds;  
    mFdsKnown = b.mFdsKnown;  
}

然后是Intent類

@Override  
public Object clone() {  
    return new Intent(this);  
}  
public Intent(Intent o) {  
    this.mAction = o.mAction;  
    this.mData = o.mData;  
    this.mType = o.mType;  
    this.mPackage = o.mPackage;  
    this.mComponent = o.mComponent;  
    this.mFlags = o.mFlags;  
    this.mContentUserHint = o.mContentUserHint;  
    if (o.mCategories != null) {  
        this.mCategories = new ArraySet<String>(o.mCategories);  
    }  
    if (o.mExtras != null) {  
        this.mExtras = new Bundle(o.mExtras);  
    }  
    if (o.mSourceBounds != null) {  
        this.mSourceBounds = new Rect(o.mSourceBounds);  
    }  
    if (o.mSelector != null) {  
        this.mSelector = new Intent(o.mSelector);  
    }  
    if (o.mClipData != null) {  
        this.mClipData = new ClipData(o.mClipData);  
    }  
}

用法也十分簡單,一旦我們要用的Intent與現在的一個Intent很多東西都一樣,那我們就可以直接拷貝現有的Intent,再修改不同的地方,便可以直接使用

Uri uri = Uri.parse("smsto:10086");      
Intent shareIntent = new Intent(Intent.ACTION_SENDTO, uri);      
shareIntent.putExtra("sms_body", "hello");      

Intent intent = (Intent)shareIntent.clone() ;  
startActivity(intent);

網絡請求中最常用的OkHttp中,也應用了原型模式,就在OkHttpClient類中,他實現了Cloneable接口

/** Returns a shallow copy of this OkHttpClient. */  
@Override   
public OkHttpClient clone() {  
    return new OkHttpClient(this);  
}  
private OkHttpClient(OkHttpClient okHttpClient) {  
    this.routeDatabase = okHttpClient.routeDatabase;  
    this.dispatcher = okHttpClient.dispatcher;  
    this.proxy = okHttpClient.proxy;  
    this.protocols = okHttpClient.protocols;  
    this.connectionSpecs = okHttpClient.connectionSpecs;  
    this.interceptors.addAll(okHttpClient.interceptors);  
    this.networkInterceptors.addAll(okHttpClient.networkInterceptors);  
    this.proxySelector = okHttpClient.proxySelector;  
    this.cookieHandler = okHttpClient.cookieHandler;  
    this.cache = okHttpClient.cache;  
    this.internalCache = cache != null ? cache.internalCache : okHttpClient.internalCache;  
    this.socketFactory = okHttpClient.socketFactory;  
    this.sslSocketFactory = okHttpClient.sslSocketFactory;  
    this.hostnameVerifier = okHttpClient.hostnameVerifier;  
    this.certificatePinner = okHttpClient.certificatePinner;  
    this.authenticator = okHttpClient.authenticator;  
    this.connectionPool = okHttpClient.connectionPool;  
    this.network = okHttpClient.network;  
    this.followSslRedirects = okHttpClient.followSslRedirects;  
    this.followRedirects = okHttpClient.followRedirects;  
    this.retryOnConnectionFailure = okHttpClient.retryOnConnectionFailure;  
    this.connectTimeout = okHttpClient.connectTimeout;  
    this.readTimeout = okHttpClient.readTimeout;  
    this.writeTimeout = okHttpClient.writeTimeout;  
}

 

來自:http://blog.csdn.net/u012532559/article/details/52797809

 

 本文由用戶 zhizhiyu 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!