java設計模式

1.單例模式

  • 作用
    保證在java應用程序中,一個類Class只有一個實例存在。
  • 優(yōu)點
    1.由于單例模式在內存中只有一個實例,減少了內存開銷
    2.單例模式可以避免對資源的多重占用
    3.單例模式可以在系統(tǒng)設置全局的訪問點,優(yōu)化和共享資源訪問。
  • 使用情況
    1.建立目錄,數據庫連接的單線程操作。
    2.某個需要被頻繁訪問的實例對象。
    第一種形式
 public class Singleton {

    /* 持有私有靜態(tài)實例,防止被引用,此處賦值為null,目的是實現延遲加載 */
    private static Singleton instance = null;

    /* 私有構造方法,防止被實例化 */
    private Singleton() {
    }

    /* 懶漢式:第一次調用時初始Singleton,以后就不用再生成了
    靜態(tài)方法,創(chuàng)建實例 */
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

但是這種方法存在一個問題,當對數據庫進行頻繁的讀寫操作時,會發(fā)生嚴重的不同步問題。
解決方式
給getInstance方法加個鎖唄!在這里我們可以使用synchronized關鍵字可以同步方法和同步代碼塊,所以:

 public static synchronized Singleton getInstance() {  

           if (instance == null) {  
                   instance = new Singleton();  
               }  
             return instance;  
 } 

或者

public static Singleton getInstance() {  

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

建議使用第二種方式,對代碼段加鎖。這樣可以減少線程阻塞時間。

2.Factory(工廠模式)

定義一個用于創(chuàng)建對象的接口,讓子類決定實例化哪一個類。工廠方法使一個類的實例化延遲到子類,對同一個接口的管理類進行管理和實例化創(chuàng)建。
假設需求如下:
動物Animal,它有行為move()。有兩個實現類cat和dog。為了統(tǒng)一管理和創(chuàng)建我們設計一個工廠模式。   同時兩個子類有各自的行為,Cat有eatFish(),Dog有eatBone().

Animal接口

interface animal {
    void move();
}

Cat類:

public class Cat implements Animal{

    @Override
    public void move() {
        // TODO Auto-generated method stub
        System.out.println("我是只肥貓,不愛動");
    }
    public void eatFish() {  
        System.out.println("愛吃魚");
    } 
}

Dog類:

public class Dog implements Animal{

    @Override
    public void move() {
        // TODO Auto-generated method stub
        System.out.println("我是狗,跑的快");
    }
    public void eatBone() {  
        System.out.println("愛吃骨頭");
    } 
}

工廠類

public class Factory {

    //靜態(tài)工廠方法
    //多處調用,不需要實例工廠類 
     public static Cat produceCat() {  
            return new Cat();  
        } 
     public static Dog produceDog() {  
            return new Dog();  
        }
//當然也可以一個方法,通過傳入參數,switch實現
}

使用:

Animal cat = Factory.produceCat();
cat.move();
//-----------------------------
Dog dog = Factory.produceDog();
dog.move();
dog.eatBone();
  • 作用
    工廠模式在業(yè)界運用十分廣泛,如果都用new來生成對象,隨著項目的擴展,animal還可以生出許多其他兒子來,當然兒子還有兒子,同時也避免不了對以前代碼的修改(比如加入后來生出兒子的實例),怎么管理,想著就是一團糟。

Animal cat = Factory.produceCat();
 這里實例化了Animal但不涉及到Animal的具體子類(減少了它們之間的偶合聯系性),達到封裝效果,也就減少錯誤修改的機會。

Java面向對象的原則,封裝(Encapsulation)和分派(Delegation)告訴我們:具體事情做得越多,越容易范錯誤,

一般來說,這樣的普通工廠就可以滿足基本需求。但是我們如果要新增一個Animal的實現類panda,那么必然要在工廠類里新增了一個生產panda的方法。就違背了 閉包的設計原則(對擴展要開放對修改要關閉) ,于是有了抽象工廠模式。

2.1Abstract Factory(抽象工廠)

抽象工廠模式提供一個創(chuàng)建一系列相關或相互依賴對象的接口,而無需指定它們具體的類。   啥意思?就是把生產抽象成一個接口,每個實例類都對應一個工廠類(普通工廠只有一個工廠類),同時所有工廠類都繼承這個生產接口。

生產接口Provider:

interface Provider {
    Animal produce(); 
}

每個產品都有自己的工廠類

public class CatFactory implements Provider{

    @Override
    public Animal produce() {
        // TODO Auto-generated method stub
        return new Cat();
    }
}

public class DogFactory implements Provider{

    @Override
    public Animal produce() {
        // TODO Auto-generated method stub
        return new Dog();
    }
}

產品生產

Provider provider = new CatFactory();
Animal cat =provider.produce();
cat.move();

現在我們要加入panda,直接新建一個pandaFactory就行了,這樣我們系統(tǒng)就非常靈活,具備了動態(tài)擴展功能。

2.2android中的Factory

例如AsyncTack的抽象工廠的實現:

工廠的抽象:

59 public interface ThreadFactory {
//省略為備注
69    Thread newThread(Runnable r);
70 }

產品的抽象(new Runnable就是其實現類):

56   public interface Runnable {
//省略為備注
68    public abstract void run();
69 }

AsyncTask中工廠類的實現:

185    private static final ThreadFactory sThreadFactory = new ThreadFactory() {
186        private final AtomicInteger mCount = new AtomicInteger(1);
187
188        public Thread newThread(Runnable r) {
189            return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
190        }
191    };

3.適配器模式。

我們經常要遇到要將兩個沒有關系類組合類一起使用,第一個方案是修改兩個類的接口。第二種方法就是我們要講到的adapter。

模式中的角色
需要適配的類(Adaptee):需要適配的類
適配器(Adapter):通過包裝一個需要適配的對象,把原接口轉換成目標接口。
目標接口:客戶所期待的接口,可以是具體抽象的類,也可以是接口。
// 需要適配的類

class Adaptee {  
    public void specificRequest() {  
        System.out.println("需要適配的類");  
    }  
}  
  
// 目標接口  
interface Target {  
    public void request();  
} 

實現方式

// 適配器類實現標準接口
class Adapter implements Target{
    // 直接關聯被適配類
    private Adaptee adaptee;
    
    // 可以通過構造函數傳入具體需要適配的被適配類對象
    public Adapter (Adaptee adaptee) {
        this.adaptee = adaptee;
    }
    
    public void request() {
        // 這里是使用委托的方式完成特殊功能
        this.adaptee.specificRequest();
    }
}

// 測試類
public class Client {
    public static void main(String[] args) {
        // 需要先創(chuàng)建一個被適配類的對象作為參數
        Target adapter = new Adapter(new Adaptee());
        adapter.request();
    }
}

如果Target不是接口而是一個具體的類的情況,這里的Adapter直接繼承Target就可以了。
如果Target和 Adaptee都是接口,并且都有實現類。 可以通過Adapter實現兩個接口來完成適配。   還有一種叫PluggableAdapters,可以動態(tài)的獲取幾個adapters中一個。使用Reflection技術,可以動態(tài)的發(fā)現類中的Public方法。

優(yōu)點
系統(tǒng)需要使用現有的類,而此類的接口不符合系統(tǒng)的需要。那么通過適配器模式就可以讓這些功能得到更好的復用。   將目標類和適配者類解耦,通過引入一個適配器類重用現有的適配者類,而無需修改原有代碼,更好的擴展性。
缺點
過多的使用適配器,會讓系統(tǒng)非常零亂,不易整體進行把握。比如,明明看到調用的是A接口,其實內部被適配成了B接口的實現。如果不是必要,不要使用適配器,而是直接對系統(tǒng)進行重構。

3.1Android的Adapter

android中的Adapter就有很多了,這個大家都經常用。   Adapter是AdapterView視圖與數據之間的橋梁,Adapter提供對數據的訪問,也負責為每一項數據產生一個對應的View。


BaseAdapter
BaseAdapter

BaseAdapter的部分源碼:

30public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
31    private final DataSetObservable mDataSetObservable = new DataSetObservable();
32
33    public boolean hasStableIds() {
34        return false;
35    }
36    
37    public void registerDataSetObserver(DataSetObserver observer) {
38        mDataSetObservable.registerObserver(observer);
39    }
40
41    public void unregisterDataSetObserver(DataSetObserver observer) {
42        mDataSetObservable.unregisterObserver(observer);
43    }

4.責任鏈模式

使多個對象都有機會處理請求,從而避免請求的發(fā)送者和接受者之間的耦合關系。將這些對象連成一條鏈,并沿著這條鏈傳遞該請求,直到有一個對象處理它為止。發(fā)出這個請求的客戶端并不知道鏈上的哪一個對象最終處理這個請求,這使得系統(tǒng)可以在不受客戶影響的情況下動態(tài)的重新組織和分配責任。

編程中小體現:

if(a<10){
    ...
}
else if (a<20){
    ...
}
else if(a<30){
    ...
}
else{
    ...
}

程序必須依次掃描每個分支進行判斷,找到對應的分支處理。

責任鏈模式的優(yōu)點
可以降低系統(tǒng)的耦合度(請求者與處理者代碼分離),簡化對象的相互連接,同時增強給對象指派職責的靈活性,增加新的請求方式處理類也很方便;
責任鏈模式的缺點
不能保證請求一定被接收,且由于比較長的責任鏈,請求的處理可能涉及到多個對象,系統(tǒng)性能將受到一定的影響,而且在進行代碼調試時不太方便。每次都是從鏈頭開始,這也正是鏈表的缺點。

4.1Android中的責任鏈模式

1、dispatchTouchEvent作用:決定事件是否由onInterceptTouchEvent來攔截處理。
返回super.dispatchTouchEvent時,由onInterceptTouchEvent來決定事件的流向
返回false時,會繼續(xù)分發(fā)事件,自己內部只處理了ACTION_DOWN
返回true時,不會繼續(xù)分發(fā)事件,自己內部處理了所有事件(ACTION_DOWN,ACTION_MOVE,ACTION_UP)

2、onInterceptTouchEvent作用:攔截事件,用來決定事件是否傳向子View
返回true時,攔截后交給自己的onTouchEvent處理
返回false時,交給子View來處理

3、onTouchEvent作用:事件最終到達這個方法
返回true時,內部處理所有的事件,換句話說,后續(xù)事件將繼續(xù)傳遞給該view的onTouchEvent()處理
返回false時,事件會向上傳遞,由onToucEvent來接受,如果最上面View中的onTouchEvent也返回false的話,那么事件就會消失

1.如果ViewGroup找到了能夠處理該事件的View,則直接交給子View處理,自己的onTouchEvent不會被觸發(fā);
2.一個點擊事件產生后,它的傳遞過程如下:
Activity->Window->View。頂級View接收到事件之后,就會按相應規(guī)則去分發(fā)事件。如果一個View的onTouchEvent方法返回false,那么將會交給父容器的onTouchEvent方法進行處理,逐級往上,如果所有的View都不處理該事件,則交由Activity的onTouchEvent進行處理。 
3.如果某一個View開始處理事件,如果他不消耗ACTION_DOWN事件(也就是onTouchEvent返回false),則同一事件序列比如接下來進行ACTION_MOVE,則不會再交給該View處理。
4.可以通過復寫onInterceptTouchEvent(ev)方法,攔截子View的事件(即return true),把事件交給自己處理,則會執(zhí)行自己對應的onTouchEvent方法。
5.子View可以通過調用getParent().requestDisallowInterceptTouchEvent(true); 阻止ViewGroup對其MOVE或者UP事件進行攔截; 
6.ViewGroup默認不攔截任何事件。
7.諸如TextView、ImageView這些不作為容器的View,一旦接受到事件,就調用onTouchEvent方法,它們本身沒有onInterceptTouchEvent方法。正常情況下,它們都會消耗事件(返回true),除非它們是不可點擊的(clickable和longClickable都為false),那么就會交由父容器的onTouchEvent處理?!?br> 8.點擊事件分發(fā)過程如下 dispatchTouchEvent—->OnTouchListener的onTouch方法—->onTouchEvent–>OnClickListener的onClick方法。也就是說,我們平時調用的setOnClickListener,優(yōu)先級是最低的,所以,onTouchEvent或OnTouchListener的onTouch方法如果返回true,則不響應onClick方法…

5.Observer(觀察者模式)

有時被稱作發(fā)布、訂閱模式,觀察者模式定義了一種一對多的依賴關系,讓多個觀察者對象同時監(jiān)聽某一主題對象,這個主題對象在狀態(tài)發(fā)生變化時,會通知所有的觀察者對象,使他們能夠自動更新自己。
將一個系統(tǒng)分割成一個一些類相互協(xié)作的類有一個不好的副作用,那就是需要維護相關對象間的一致性。我們不希望為了維持一致性而使各類緊密耦合,這樣會給維護、擴展和重用都帶來不便。觀察者就是解決這類的耦合關系的(依賴關系并未完全解除,抽象通知者依舊依賴抽象的觀察者)。

觀察者模組成
①抽象主題(Subject)

它把所有觀察者對象的引用保存到一個聚集里,每個主題都可以有任何數量的觀察者。抽象主題提供一個接口,可以增加和刪除觀察者對象。

②具體主題(ConcreteSubject)

將有關狀態(tài)存入具體觀察者對象;在具體主題內部狀態(tài)改變時,給所有登記過的觀察者發(fā)出通知。

③抽象觀察者(Observer)

為所有的具體觀察者定義一個接口,在得到主題通知時更新自己。

④具體觀察者(ConcreteObserver)

實現抽象觀察者角色所要求的更新接口,以便使本身的狀態(tài)與主題狀態(tài)協(xié)調。

言語蒼白,上代碼:

//抽象觀察者
public interface Observer
{
  public void update(String str);
    
}
//具體觀察者
public class ConcreteObserver implements Observer{
    @Override
    public void update(String str) {
        // TODO Auto-generated method stub
        System.out.println(str);
    }
}
//抽象主題
public interface Subject
{
    public void addObserver(Observer observer);
    public void removeObserver(Observer observer);
    public void notifyObservers(String str);
}
//具體主題
public class ConcreteSubject implements Subject{
    // 存放觀察者
    private List<Observer> list = new ArrayList<Observer>();
    @Override
    public void addObserver(Observer observer) {
        // TODO Auto-generated method stub
        list.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        // TODO Auto-generated method stub
        list.remove(observer);
    }

    @Override
    public void notifyObservers(String str) {
        // TODO Auto-generated method stub
        for(Observer observer:list){
            observer.update(str);
        }
    }
}

下面是測試類:

/**
 * @author fanrunqi
 */
public class Test {
     public static void main(String[] args) {
        //一個主題
         ConcreteSubject eatSubject = new ConcreteSubject();
         //兩個觀察者
         ConcreteObserver personOne = new ConcreteObserver();
         ConcreteObserver personTwo = new ConcreteObserver();
         //觀察者訂閱主題
         eatSubject.addObserver(personOne);
         eatSubject.addObserver(personTwo);
         
         //通知開飯了
         eatSubject.notifyObservers("開飯啦");
    }
}

“關于代碼你有什么想說的?” “沒有,都在代碼里了” “(⊙o⊙)哦.....”

6.建造者模式

建造者模式:是將一個復雜的對象的構建與它的表示分離(同構建不同表示),使得同樣的構建過程可以創(chuàng)建不同的表示。

一個人活到70歲以上,都會經歷這樣的幾個階段:嬰兒,少年,青年,中年,老年。并且每個人在各個階段肯定是不一樣的,世界上不存在兩個人在人生的這5個階段的生活完全一樣,但是活到70歲以上的人,都經歷了這幾個階段是肯定的。實際上這是一個比較經典的建造者模式的例子了。

將復雜的內部創(chuàng)建封裝在內部,對于外部調用的人來說,只需要傳入建造者和建造工具,對于內部是如何建造成成品的,調用者無需關心。

建造者通常有以下角色:
① Builder:一個抽象接口,用來規(guī)范產品對象的各個組成成分的建造。
② ConcreteBuilder:實現Builder接口,針對不同的商業(yè)邏輯,具體化復雜對象的各部分的創(chuàng)建,在建造過程完成后,提供產品的實例。
③ Director:指導者,調用具體建造者來創(chuàng)建復雜對象的各個部分,不涉及具體產品的信息,只負責保證對象各部分完整創(chuàng)建或按某種順序創(chuàng)建。
④ Product:要創(chuàng)建的復雜對象。

與抽象工廠的區(qū)別:在建造者模式里,有個指導者,由指導者來管理建造者,用戶是與指導者聯系的,指導者聯系建造者最后得到產品。即建造模式可以強制實行一種分步驟進行的建造過程。

Product和產品的部分Part接口

 public interface Product { }
 public interface Part { }
Builder:

 public interface Builder { 
    void buildPartOne(); 
    void buildPartTwo(); 
  
    Product getProduct(); 
  } 
ConcreteBuilder:

//具體建造工具
  public class ConcreteBuilder implements Builder { 
    Part partOne, partTwo; 

    public void buildPartOne() {
      //具體構建代碼
    }; 
    public void buildPartTwo() { 
      //具體構建代碼
    }; 
     public Product getProduct() { 
      //返回最后組裝的產品
    }; 
  }
Director :

 public class Director {
    private Builder builder; 
  
    public Director( Builder builder ) { 
      this.builder = builder; 
    } 
    public void construct() { 
      builder.buildPartOne();
      builder.buildPartTwo();
    } 
  } 

建造:

ConcreteBuilder builder = new ConcreteBuilder();
Director director = new Director(builder); 
//開始各部分建造 
director.construct(); 
Product product = builder.getResult();

優(yōu)點

客戶端不必知道產品內部組成的細節(jié)。

具體的建造者類之間是相互獨立的,對系統(tǒng)的擴展非常有利。

由于具體的建造者是獨立的,因此可以對建造過程逐步細化,而不對其他的模塊產生任何影響

適用場合:
創(chuàng)建一些復雜的對象時,這些對象的內部組成構件間的建造順序是穩(wěn)定的,但是對象的內部組成構件面臨著復雜的變化。

要創(chuàng)建的復雜對象的算法,獨立于該對象的組成部分,也獨立于組成部分的裝配方法時。

6.1Android中的Builder

android中的Dialog就使用了Builder Pattern,下面來看看AlertDialog的部分源碼。

371    public static class Builder {
372        private final AlertController.AlertParams P;
373        private int mTheme;

393        public Builder(Context context, int theme) {
394            P = new AlertController.AlertParams(new ContextThemeWrapper(
395                    context, resolveDialogTheme(context, theme)));
396            mTheme = theme;
397        }

AlertDialog的Builder 是一個靜態(tài)內部類,沒有定義Builder 的抽象接口。   對AlertDialog設置的屬性會保存在Build類的成員變量P(AlertController.AlertParams)中。
Builder類中部分方法:

416        public Builder setTitle(int titleId) {
417            P.mTitle = P.mContext.getText(titleId);
418            return this;
419        }
452        public Builder setMessage(int messageId) {
453            P.mMessage = P.mContext.getText(messageId);
454            return this;
455        }
        
525        public Builder setPositiveButton(CharSequence text, final OnClickListener listener) {
526            P.mPositiveButtonText = text;
527            P.mPositiveButtonListener = listener;
528            return this;
529        }

而show()方法會返回一個結合上面設置的dialog實例

991        public AlertDialog show() {
992            AlertDialog dialog = create();
993            dialog.show();
994            return dialog;
995        }
996    }
997    
998}
972        public AlertDialog create() {
973            final AlertDialog dialog = new AlertDialog(P.mContext, mTheme, false);
974            P.apply(dialog.mAlert);
975            dialog.setCancelable(P.mCancelable);
976            if (P.mCancelable) {
977                dialog.setCanceledOnTouchOutside(true);
978            }
979            dialog.setOnCancelListener(P.mOnCancelListener);
980            dialog.setOnDismissListener(P.mOnDismissListener);
981            if (P.mOnKeyListener != null) {
982                dialog.setOnKeyListener(P.mOnKeyListener);
983            }
984            return dialog;
985        }

簡單建造:

new AlertDialog.Builder(context)
 .setTitle("標題") 
 .setMessage("消息框")
 .setPositiveButton("確定", null)
 .show();

7.備忘錄模式

備忘錄模式又叫做快照模式(Snapshot Pattern)或Token模式,是對象的行為模式。
備忘錄對象是一個用來存儲另外一個對象內部狀態(tài)的快照的對象。備忘錄模式的用意是在不破壞封裝的條件下,將一個對象的狀態(tài)捕捉(Capture)住,并外部化,存儲起來,從而可以在將來合適的時候把這個對象還原到存儲起來的狀態(tài)。備忘錄模式常常與命令模式和迭代子模式一同使用。

備忘錄模式所涉及的角色有三個:

① Originator(發(fā)起人): 負責創(chuàng)建一個備忘錄Memento,用以記錄當前時刻它的內部狀態(tài),并可使用備忘錄恢復內部狀態(tài)。Originator可根據需要決定Memento存儲Originator的哪些內部狀態(tài)。

② Memento(備忘錄): 負責存儲Originnator對象的內部狀態(tài),并可防止Originator以外的其他對象訪問備忘錄Memento,備忘錄有兩個接口,Caretaker只能看到備忘錄的窄接口,它只能將備忘錄傳遞給其他對象。

③、 Caretaker(管理者):負責保存好備忘錄Memento,不能對備忘錄的內容進行操作或檢查。

public class Originator {

    private String state;
    /**
     * 工廠方法,返回一個新的備忘錄對象
     */
    public Memento createMemento(){
        return new Memento(state);
    }
    /**
     * 將發(fā)起人恢復到備忘錄對象所記載的狀態(tài)
     */
    public void restoreMemento(Memento memento){
        this.state = memento.getState();
    }
    
    public String getState() {
        return state;
    }
    
    public void setState(String state) {
        this.state = state;
        System.out.println("當前狀態(tài):" + this.state);
    }
    
}
public class Memento {
    
    private String state;
    
    public Memento(String state){
        this.state = state;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }
    
}
public class Caretaker {

    private Memento memento;
    /**
     * 備忘錄的取值方法
     */
    public Memento retrieveMemento(){
        return this.memento;
    }
    /**
     * 備忘錄的賦值方法
     */
    public void saveMemento(Memento memento){
        this.memento = memento;
    }
}

使用:

Originator o = new Originator();
Caretaker c = new Caretaker();
//改變負責人對象的狀態(tài)
o.setState("On");
//創(chuàng)建備忘錄對象,并將發(fā)起人對象的狀態(tài)儲存起來
 c.saveMemento(o.createMemento());
//修改發(fā)起人的狀態(tài)
o.setState("Off");
//恢復發(fā)起人對象的狀態(tài)
 o.restoreMemento(c.retrieveMemento());

不需要了解對象的內部結構的情況下備份對象的狀態(tài),方便以后恢復。

7.1Android中的Memento

Activity的onSaveInstanceState和onRestoreInstanceState就是通過Bundle(相當于備忘錄對象)這種序列化的數據結構來存儲Activity的狀態(tài),至于其中存儲的數據結構,這兩個方法不用關心。

1365    protected void onSaveInstanceState(Bundle outState) {
1366        outState.putBundle(WINDOW_HIERARCHY_TAG, mWindow.saveHierarchyState());
1367        Parcelable p = mFragments.saveAllState();
1368        if (p != null) {
1369            outState.putParcelable(FRAGMENTS_TAG, p);
1370        }
1371        getApplication().dispatchActivitySaveInstanceState(this, outState);
1372    }
1019    protected void onRestoreInstanceState(Bundle savedInstanceState) {
1020        if (mWindow != null) {
1021            Bundle windowState = savedInstanceState.getBundle(WINDOW_HIERARCHY_TAG);
1022            if (windowState != null) {
1023                mWindow.restoreHierarchyState(windowState);
1024            }
1025        }
1026    }

8. Prototype(原型模式)

原型模式,能快速克隆出一個與已經存在對象類似的另外一個我們想要的新對象。   工作原理是:通過將一個原型對象傳給那個要發(fā)動創(chuàng)建的對象,這個要發(fā)動創(chuàng)建的對象通過請求原型對象拷貝它們自己來實施創(chuàng)建。

分為深拷貝和淺拷貝。深拷貝就是把對象里面的引用的對象也要拷貝一份新的對象,并將這個新的引用對象作為拷貝的對象引用(多讀兩遍)。

一般使用原型模式有個明顯的特點,就是實現cloneable的clone()方法。

在Intent源碼中:

4084    @Override
4085    public Object clone() {
4086        return new Intent(this);
4087    }

這里Intent通過實現Cloneable接口來實現原型拷貝。

9. Strategy(策略模式)      定義:有一系列的算法,將每個算法封裝起來(每個算法可以封裝到不同的類中),各個算法之間可以替換,策略模式讓算法獨立于使用它的客戶而獨立變化。

舉例:   一個影碟機,你往里面插什么碟子,就能放出什么電影。   屬性動畫,設置不同的插值器對象,就可以得到不同的變化曲線。   返回值解析,傳入什么樣的解析器,就可以把二進制數據轉換成什么格式的數據,比如String、Json、XML。

策略模式其實就是多態(tài)的一個淋漓精致的體現。

在android中不同Animation動畫的實現,主要是依靠Interpolator的不同而實現的。

401     public void setInterpolator(Interpolator i) {
402         mInterpolator = i;
403     }

10. Template(模板模式)

定義:定義一個操作中的算法框架,而將一些步驟延遲到子類中,使得子類可以不改變一個算法的結構即可重定義該算法的某些特定的步驟。      實現流程已經確定,實現細節(jié)由子類完成。      生命周期對于我們都不陌生,它就是典型的Template模式,在具體流程確定的情況下,至于我們要復寫生命周期那些方法,實現那些功能由繼承activity的子類去具體實現。

關鍵在于必須有具體的執(zhí)行流程,比如AsyncTask。

11.proxy(代理模式)

定義:為其他對象提供一種代理以控制對這個對象的訪問。   代理: 在出發(fā)點到目的地之間有一道中間層。

應用:Android跨進程通信方式 ,建議去了解一下Binder機制。

12. Interpreter(解釋器模式)

定義語言的文法,并且建立一個解釋器來解釋該語言中的句子。

比如Android中通過PackageManagerService來解析AndroidManifest.xml中定義的Activity、service等屬性。

13. State(狀態(tài)模式)

行為是由狀態(tài)來決定的,不同狀態(tài)下有不同行為。

注意:狀態(tài)模式的行為是平行的、不可替換的,策略模式的行為是彼此獨立可相互替換的。

體現:不同的狀態(tài)執(zhí)行不同的行為,當WIFI開啟時,自動掃描周圍的接入點,然后以列表的形式展示;當wifi關閉時則清空。

14. Command(命令模式)

我們有很多命令,把它們放在一個下拉菜單中,用戶通過先選擇菜單再選擇具體命令,這就是Command模式。

本來用戶(調用者)是直接調用這些命令的,在菜單上打開文檔,就直接指向打開文檔的代碼,使用Command模式,就是在這兩者之間增加一個中間者,將這種直接關系拗斷,同時兩者之間都隔離,基本沒有關系了。      顯然這樣做的好處是符合封裝的特性,降低耦合度,有利于代碼的健壯性 可維護性 還有復用性。Command是將對行為進行封裝的典型模式,Factory是將創(chuàng)建進行封裝的模式。

android底層邏輯對事件的轉發(fā)處理就用到了Command模式。

15. Iterator(迭代模式)

提供一種方法順序訪問一個容器對象中的各個元素,而不需要暴露該對象的內部表示。

應用:

在Java中的Iterator類。

Android中的 Cursor。

cursor.moveToFirst();

16. Composite(組合模式)

將對象以樹形結構組織起來,以達成“部分-整體” 的層次結構,使得客戶端對單個對象和組合對象的使用具有一致性。

Android中View的結構是樹形結構,每個ViewGroup包含一系列的View,而ViewGroup本身又是View。這是Android中非常典型的組合模式。

17. Flyweight(共享模式/享元模式)

定義:避免大量擁有相同內容的小類的開銷(如耗費內存),使大家共享一個類(元類)。

面向對象語言的原則就是一切都是對象,但是如果真正使用起來,有時對象數可能顯得很龐大,比如,字處理軟件,如果以每個文字都作為一個對象,幾千個字,對象數就是幾千,無疑耗費內存,那么我們還是要"求同存異",找出這些對象群的共同點,設計一個元類,封裝可以被共享的類,另外,還有一些特性是取決于應用(context),是不可共享的,這也Flyweight中兩個重要概念內部狀態(tài)intrinsic和外部狀態(tài)extrinsic之分。

說白點,就是先捏一個的原始模型,然后隨著不同場合和環(huán)境,再產生各具特征的具體模型,很顯然,在這里需要產生不同的新對象,所以Flyweight模式中常出現Factory模式。Flyweight的內部狀態(tài)是用來共享的,Flyweight factory負責維護一個Flyweight pool(模式池)來存放內部狀態(tài)的對象。

Flyweight模式是一個提高程序效率和性能的模式,會大大加快程序的運行速度。應用場合很多:比如你要從一個數據庫中讀取一系列字符串,這些字符串中有許多是重復的,那么我們可以將這些字符串儲存在Flyweight池(pool)中。

在Android線程通信中,每次獲取Message時調Message.obtain()其實就是從消息池中取出可重復使用的消息,避免產生大量的Message對象。

對于設計模式沒有必要去記憶,知道就好,說白了設計模式只是一種處理問題的方法,在遇到具體的問題時,可能會使用一些技巧,而這個技巧有可能是幾個模式結合,都只是運用而已。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容