Android開發(fā)常見的設(shè)計(jì)模式

單例模式

概念:

確保某一個(gè)類只有一個(gè)實(shí)例,而且自行實(shí)例化并向整個(gè)系統(tǒng)提供這個(gè)實(shí)例。

優(yōu)點(diǎn):
  • 對(duì)于那些比較耗內(nèi)存的類,只實(shí)例化一次可以大大提高性能,尤其是在移動(dòng)開發(fā)中。
  • 保持程序運(yùn)行的時(shí)候,始終只有一個(gè)實(shí)例存在內(nèi)存中
例子:
public class Singleton {
    private static volatile Singleton instance = null;

    private Singleton(){
    }
 
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}
編寫單例模式,需要記住的特點(diǎn):
  • 必須防止外部可以調(diào)用構(gòu)造函數(shù)進(jìn)行實(shí)例化,因此構(gòu)造函數(shù)必須私有化。
  • 必須定義一個(gè)靜態(tài)函數(shù)獲得該單例getInstance();
  • 單例使用volatile修飾,volatile可以保證不同線程對(duì)這個(gè)變量進(jìn)行操作時(shí)的可見性,即一個(gè)線程修改了某個(gè)變量的值,這新值對(duì)其他線程來說是立即可見的。
  • 使用synchronized 進(jìn)行同步處理,并且雙重判斷是否為null,我們看到synchronized (Singleton.class)里面又進(jìn)行了是否為null的判斷,這是因?yàn)橐粋€(gè)線程進(jìn)入了該代碼,如果另一個(gè)線程在等待,這時(shí)候前一個(gè)線程創(chuàng)建了一個(gè)實(shí)例出來完畢后,另一個(gè)線程獲得鎖進(jìn)入該同步代碼,實(shí)例已經(jīng)存在,沒必要再次創(chuàng)建,因此這個(gè)判斷是否是null還是必須的。

Build模式

概念:

將一個(gè)復(fù)雜對(duì)象的構(gòu)建與它的表示分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示。

優(yōu)點(diǎn):

提高代碼的可讀性。

例子:
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);
        }
    }
}

編寫一個(gè)Person類,里面有一個(gè)叫Builder的靜態(tài)內(nèi)部類,他們的屬性是一樣的。把Person類的構(gòu)造函數(shù)私有化,參數(shù)是Builder,把Builder類中的屬性對(duì)應(yīng)賦值給Person類。Builder類里面有對(duì)應(yīng)各個(gè)屬性名的方法,有點(diǎn)像Setter方法,唯一不同是返回值返回的是this。Builder類里面還有build方法,返回Person對(duì)象,return new Person(this);

然后我們就可以這樣創(chuàng)建Person類對(duì)象了:

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

Android 里面的AlertDialog,StringBuilder,StringBuffer 都有運(yùn)用到Build模式。

觀察者模式

概念:

定義對(duì)象間的一種一對(duì)多的依賴關(guān)系,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)送改變時(shí),所有依賴于它的對(duì)象都能得到通知并被自動(dòng)更新

例子:

天氣對(duì)象:

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 + '\'' +
                '}';
    }
}

被觀察者:

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);
        }
    }

}

觀察者需要實(shí)現(xiàn)的接口:

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

Main函數(shù):

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("晴轉(zhuǎn)多云");
        observable.notifyObservers(weather);

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

        observable.unregister(observer1);

        Weather weather2=new Weather("臺(tái)風(fēng)");
        observable.notifyObservers(weather2);

    }
}

Android的廣播機(jī)制就是使用的觀察者模式。

原型模式

概念:

用原型實(shí)例指定創(chuàng)建對(duì)象的種類,并通過拷貝這些原型創(chuàng)建新的對(duì)象。

要實(shí)現(xiàn)原型模式,只需要按照下面的幾個(gè)步驟去實(shí)現(xiàn)即可。

  • 實(shí)現(xiàn)Clone接口:
public class Person implements Cloneable{

}
  • 重寫Object的clone方法
@Override
public Object clone(){
    return null;
}
  • 實(shí)現(xiàn)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;
}
  • 測(cè)試:
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);
    }
}
  • 一個(gè)對(duì)象需要提供給其他對(duì)象訪問,而且各個(gè)調(diào)用者可能都需要修改其值時(shí),可以考慮使用原型模式拷貝多個(gè)對(duì)象供調(diào)用者使用,即保護(hù)性拷貝。

注意:這里的克隆是淺克隆,只是克隆引用,所以,如果要克隆ArrayList,需要再克隆一次。

person.hobbies=(ArrayList<String>)this.hobbies.clone();

策略模式

概念:

策略模式定義了一些列的算法,并將每一個(gè)算法封裝起來,而且使它們還可以相互替換。策略模式讓算法獨(dú)立于使用它的客戶而獨(dú)立變換。

  • 首先,需要定義一個(gè)策略接口。
public interface Strategy {
    void travel();
}
  • 然后根據(jù)不同的出行方式實(shí)行對(duì)應(yīng)的接口
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");
    }

}
  • 此外還需要一個(gè)包裝策略的類,并調(diào)用策略接口中的方法
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();
        }
    }
}

可以看到,應(yīng)用了策略模式后,如果我們想增加新的出行方式,完全不必要修改現(xiàn)有的類,我們只需要實(shí)現(xiàn)策略接口即可,這就是面向?qū)ο笾械膶?duì)擴(kuò)展開放準(zhǔn)則。假設(shè)現(xiàn)在我們?cè)黾恿艘环N自行車出行的方式。只需新增一個(gè)類即可。

參考:Android開發(fā)中常見的設(shè)計(jì)模式

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

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,554評(píng)論 19 139
  • 原文鏈接:http://blog.csdn.net/zhangerqing http://www.cnblogs....
    孤獨(dú)雜貨鋪閱讀 1,638評(píng)論 0 3
  • 面向?qū)ο蟮牧笤瓌t 單一職責(zé)原則 所謂職責(zé)是指類變化的原因。如果一個(gè)類有多于一個(gè)的動(dòng)機(jī)被改變,那么這個(gè)類就具有多于...
    JxMY閱讀 1,027評(píng)論 1 3
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,692評(píng)論 18 399
  • 設(shè)計(jì)模式匯總 一、基礎(chǔ)知識(shí) 1. 設(shè)計(jì)模式概述 定義:設(shè)計(jì)模式(Design Pattern)是一套被反復(fù)使用、多...
    MinoyJet閱讀 4,093評(píng)論 1 15

友情鏈接更多精彩內(nèi)容