日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
談?wù)?3種設(shè)計模式在Android項目中的應(yīng)用

前言

本文將結(jié)合實際談?wù)?3種設(shè)計模式,每種設(shè)計模式涉及

站在用戶的角度思考問題,與客戶深入溝通,找到青岡網(wǎng)站設(shè)計與青岡網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗,讓設(shè)計與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個性化、用戶體驗好的作品,建站類型包括:成都做網(wǎng)站、成都網(wǎng)站建設(shè)、成都外貿(mào)網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣、域名注冊網(wǎng)站空間、企業(yè)郵箱。業(yè)務(wù)覆蓋青岡地區(qū)。

  • 定義:抽象化的定義與通俗的描述,盡量說明清楚其含義與應(yīng)用場景
  • 示例:如果項目中有使用過該模式,則會給出項目中的代碼,否則會給出盡可能簡單好理解的java代碼
  • Android:該設(shè)計模式在Android源碼框架中哪些地方有使用到
  • 重構(gòu):項目中是否存在可以用該模式進行重構(gòu)的地方,如果有會給出重構(gòu)前與重構(gòu)后的代碼或者思路

用這種方式進行介紹設(shè)計模式,旨在結(jié)合每天都在接觸的Android實際項目開發(fā)更好地理解設(shè)計模式,拉近與設(shè)計模式的距離,同時在實際開發(fā)與重構(gòu)中,思考可以應(yīng)用的重構(gòu)手段與設(shè)計模式,既能保證寫出復(fù)用性與可靠性更高的代碼,也是對如何利用重構(gòu)與設(shè)計模式這兩大支柱進行優(yōu)雅編程的最佳實踐與總結(jié)。

同時一次性以這種方式介紹23種設(shè)計模式,也是出于既然要使用一個模式,那么就應(yīng)該要先知道這么一個模式的想法,四人幫的《設(shè)計模式》也是對經(jīng)驗的總結(jié),但是有巨人托著你上去,又何必自己再摸黑造梯子。

重構(gòu)不是本章的重點,因為這也是一個非常大的話題,這邊只討論實際項目中是否有存在一些能用設(shè)計模式進行改善的地方。
關(guān)于重構(gòu),這邊也有寫了一篇博文 重構(gòu):改善既有代碼的設(shè)計 ,基本列舉了《重構(gòu):改善既有代碼的設(shè)計》中的各項要點,后續(xù)還會繼續(xù)將《重構(gòu)》中的手法與設(shè)計模式應(yīng)用到實際項目中,有所總結(jié)之后會再寫幾篇實際應(yīng)用的博文。

簡介

設(shè)計模式(Design pattern)是一套被反復(fù)使用、多數(shù)人知曉的、經(jīng)過分類編目的、代碼設(shè)計經(jīng)驗的總結(jié)。使用設(shè)計模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。 毫無疑問,設(shè)計模式于己于他人于系統(tǒng)都是多贏的,設(shè)計模式使代碼編制真正工程化,設(shè)計模式是軟件工程的基石,如同大廈的一塊塊磚石一樣。項目中合理的運用設(shè)計模式可以完美的解決很多問題,每種模式在現(xiàn)在中都有相應(yīng)的原理來與之對應(yīng),每一個模式描述了一個在我們周圍不斷重復(fù)發(fā)生的問題,以及該問題的核心解決方案,這也是它能被廣泛應(yīng)用的原因。

六大原則

單一職責原則

單一原則很簡單,就是將一組相關(guān)性很高的函數(shù)、數(shù)據(jù)封裝到一個類中。換句話說,一個類應(yīng)該有職責單一。

開閉原則

開閉原則理解起來也不復(fù)雜,就是一個類應(yīng)該對于擴展是開放的,但是對于修改是封閉的。在一開始編寫代碼時,就應(yīng)該注意盡量通過擴展的方式實現(xiàn)新的功能,而不是通過修改已有的代碼實現(xiàn),否則容易破壞原有的系統(tǒng),也可能帶來新的問題,如果發(fā)現(xiàn)沒辦法通過擴展來實現(xiàn),應(yīng)該考慮是否是代碼結(jié)構(gòu)上的問題,通過重構(gòu)等方式進行解決。

里氏替換原則

所有引用基類的地方必須能透明地使用其子類對象。本質(zhì)上就是說要好好利用繼承和多態(tài),從而以父類的形式來聲明變量(或形參),為變量(或形參)賦值任何繼承于這個父類的子類。

依賴倒置原則

依賴倒置主要是實現(xiàn)解耦,使得高層次的模塊不依賴于低層次模塊的具體實現(xiàn)細節(jié)。怎么去理解它呢,我們需要知道幾個關(guān)鍵點:

  • 高層模塊不應(yīng)該依賴底層模塊(具體實現(xiàn)),二者都應(yīng)該依賴其抽象(抽象類或接口)
  • 抽象不應(yīng)該依賴細節(jié)
  • 細節(jié)應(yīng)該依賴于抽象

在我們用的Java語言中,抽象就是指接口或者抽象類,二者都是不能直接被實例化;細節(jié)就是實現(xiàn)類,實現(xiàn)接口或者繼承抽象類而產(chǎn)生的類,就是細節(jié)。使用Java語言描述就是:各個模塊之間相互傳遞的參數(shù)聲明為抽象類型,而不是聲明為具體的實現(xiàn)類;

接口隔離原則

類之間的依賴關(guān)系應(yīng)該建立在最小的接口上。其原則是將非常龐大的、臃腫的接口拆分成更小的更具體的接口。

迪米特原則

一個對象應(yīng)該對其他的對象有最少的了解.

假設(shè)類A實現(xiàn)了某個功能,類B需要調(diào)用類A的去執(zhí)行這個功能,那么類A應(yīng)該只暴露一個函數(shù)給類B,這個函數(shù)表示是實現(xiàn)這個功能的函數(shù),而不是讓類A把實現(xiàn)這個功能的所有細分的函數(shù)暴露給B。

設(shè)計模式

單例模式

定義

確保單例類只有一個實例,并且這個單例類提供一個函數(shù)接口讓其他類獲取到這個唯一的實例。
如果某個類,創(chuàng)建時需要消耗很多資源,即new出這個類的代價很大;或者是這個類占用很多內(nèi)存,如果創(chuàng)建太多這個類實例會導(dǎo)致內(nèi)存占用太多。上述情況下就應(yīng)該使用單例模式

實際應(yīng)用

   // 單例對象
    private static AdvertPresenter mInstance;
    /**      * 私有化構(gòu)造函數(shù)      */
    private AdvertPresenter(){
    }
    /**      * 獲取AdvertPresenter實例      * @return      */
    public static AdvertPresenter getInstance() {
        if (mInstance == null) {
            synchronized (AdvertPresenter.class) {
                if (mInstance == null) {
                    mInstance = new AdvertPresenter();
                }
            }
        }
        return mInstance;
    }

Android

//獲取WindowManager服務(wù)引用
WindowManager wm = (WindowManager)getSystemService(getApplication().WINDOW_SERVICE);

其內(nèi)部就是通過單例的方式持有一個WindowManager并返回這個對象

重構(gòu)

項目中存在多次使用Random與Gson的操作,可以將Random與Gson對象封裝成單例進行使用

建造者模式

定義

將一個復(fù)雜對象的構(gòu)造與它的表示分離,使得同樣的構(gòu)造過程可以創(chuàng)建不同的表示。
主要是在創(chuàng)建某個對象時,需要設(shè)定很多的參數(shù)(通過setter方法),但是這些參數(shù)必須按照某個順序設(shè)定,或者是設(shè)置步驟不同會得到不同結(jié)果。

示例

各類自定義Dialog

Android

AlertDialog.Builer builder=new AlertDialog.Builder(context);
builder.setIcon(R.drawable.icon)
    .setTitle("title")
    .setMessage("message")
    .setPositiveButton("Button1",
        new DialogInterface.OnclickListener(){
            public void onClick(DialogInterface dialog,int whichButton){
                setTitle("click");
            }   
        })
    .create()
    .show();

重構(gòu)

暫無

原型模式

定義

用原型實例指定創(chuàng)建對象的種類,并通過拷貝這些原型創(chuàng)建新的對象。
可以在類的屬性特別多,但是又要經(jīng)常對類進行拷貝的時候可以用原型模式,這樣代碼比較簡潔,而且比較方便。
拷貝時要注意淺拷貝與深拷貝

示例

     private HashMap getClonePointMap(Map map) {
            HashMap clone = new HashMap<>();
            if (map != null) {
                Iterator iterator = map.entrySet().iterator();
                while (iterator.hasNext()) {
                    Map.Entry entry = (Map.Entry) iterator.next();
                    String key = (String) entry.getKey();
                    PointBean pointBean = (PointBean) entry.getValue();
                    if (pointBean != null) {
                        //遍歷map并將克隆對象放到新的map中
                        clone.put(key, pointBean.clone());
                    } else {
                        clone.put(key, null);
                    }
                }
            }
            return clone;
        }

Android

Intent intent = new Intent(Intent.ACTION_SENDTO, uri);
//克隆副本
Intent copyIntent=(Intetn)shareIntent.clone();

重構(gòu)

如果存在逐一去除某個對象的各項參數(shù)值,轉(zhuǎn)而賦值給另一個對象身上時,便可使用原型模式

工廠模式

簡單工廠模式

定義

建立一個工廠(一個函數(shù)或一個類方法)來制造新的對象。

示例

public static Operation createOperate(string operate) {
    Operation oper = null;
    switch (operate)
    {
        case "+":
            {
            oper = new OperationAdd();
            break;
            }
        case "-":
            {
            oper = new OperationSub();
            break;
            }
        case "*":
            {
            oper = new OperationMul();
            break;
            }
        case "/":
            {
            oper = new OperationDiv();
            break;
            }
    }
    return oper;
   }
}

Android

public Object getSystemService(String name) {
    if (getBaseContext() == null) {
        throw new IllegalStateException("System services not available to Activities before onCreate()");
    }
    //........
    if (WINDOW_SERVICE.equals(name)) {
         return mWindowManager;
    } else if (SEARCH_SERVICE.equals(name)) {
        ensureSearchManager();
        return mSearchManager;
    }
    //.......
    return super.getSystemService(name);
  }

在getSystemService方法中就是用到了簡單工廠模式,根據(jù)傳入的參數(shù)決定創(chuàng)建哪個對象,由于這些對象以單例模式提前創(chuàng)建好了,所以此處不用new了,直接把單例返回就好。

重構(gòu)

//重構(gòu)前
public class AdvertPresenter {
    ...
    private void initAdvertManager() {
        String[] platforms = mAdConfig.getAllPlatforms();
        if (platforms != null && platforms.length > 0) {
            int platformSize = platforms.length;
            for (int i = 0; i < platformSize; i++) {
                String platform = platforms[i];
                if (platform.equalsIgnoreCase(AdvertConstant.AD_PLATFORM_FACEBOOK)) {
                    FacebookAdvertManager fbAdManager = new FacebookAdvertManager();
                    mAdvertManager.put(AdvertConstant.AD_PLATFORM_FACEBOOK, fbAdManager);
                } else if (platform.equalsIgnoreCase(AdvertConstant.AD_PLATFORM_ADMOB)) {
                    AdMobAdvertManager adMobAdvertManager = new AdMobAdvertManager();
                    mAdvertManager.put(AdvertConstant.AD_PLATFORM_ADMOB, adMobAdvertManager);
                } else if (platform.equalsIgnoreCase(AdvertConstant.AD_PLATFORM_MOPUB)) {
                    MopubAdvertManager mopubAdvertManager = new MopubAdvertManager();
                    mAdvertManager.put(AdvertConstant.AD_PLATFORM_MOPUB, mopubAdvertManager);
                } else if (platform.equalsIgnoreCase(AdvertConstant.AD_PLATFORM_ADX)) {
                    AdxAdvertManager mopubAdvertManager = new AdxAdvertManager();
                    mAdvertManager.put(AdvertConstant.AD_PLATFORM_ADX, mopubAdvertManager);
                }
            }
        }
    }
    ...
}
//重構(gòu)后
public class BaseAdvertManager {
    ...
    public static BaseAdvertManager create(String platform) {
        if (platform.equalsIgnoreCase(AdvertConstant.AD_PLATFORM_FACEBOOK)) {
            return new FacebookAdvertManager();
        } else if (platform.equalsIgnoreCase(AdvertConstant.AD_PLATFORM_MOPUB)) {
            return new MopubAdvertManager();
        } else if (platform.equalsIgnoreCase(AdvertConstant.AD_PLATFORM_ADX)) {
            return new AdxAdvertManager();
        } else if (platform.equalsIgnoreCase(AdvertConstant.AD_PLATFORM_ADMOB)) {
            return new AdMobAdvertManager();
        } else {
            ***return new NullAdvertManager();***//引入NULL對象
        }
    }
    ...
}
public class AdvertPresenter {
    ...
    private void initAdvertManager() {
        String[] platforms = mAdConfig.getAllPlatforms();
        if (platforms != null && platforms.length > 0) {
            int platformSize = platforms.length;
            for (int i = 0; i < platformSize; i++) {
                String platform = platforms[i];
                mAdvertManager.put(platform, BaseAdvertManager.create(platform));
            }
        }
    }
    ...
}

工廠方法模式

定義

是定義一個創(chuàng)建產(chǎn)品對象的工廠接口,讓其子類決定實例化哪一個類,將實際創(chuàng)建工作推遲到子類當中。

示例

public abstract class Product {
    public abstract void method();
}

public class ConcreteProduct extends Prodect {
    public void method(){
        System.out.println("我是具體產(chǎn)品!");
    }
}

public  abstract class Factory{
    public abstract Product createProduct();
}

public class ConcreteFactory extends Factory{

    public Product createProduct(){
        return new ConcreteProductA();
    }
}

Android

我們在開發(fā)中會用到很多數(shù)據(jù)結(jié)構(gòu),比如ArrayList,HashMap等。我們先來看下Java中Collection部分的類集框架的簡要UML圖。

我們知道Iterator是迭代器,用來遍歷一個集合中的元素。而不同的數(shù)據(jù)結(jié)構(gòu)遍歷的方式是不一樣的,所以迭代器的實現(xiàn)也是不同的。使用工廠方法模式將迭代器的具體類型延遲到具體容器類中,比較靈活,容易擴展。

public interface Iterable {
    /**      * Returns an iterator over elements of type {@code T}.      *      * @return an Iterator.      */
    Iterator iterator();

    //省略部分代碼
}

List和Set繼承自Collection接口,Collection接口繼承于Iterable接口。所以List和Set接口也需要繼承并實現(xiàn)Iterable中的iterator()方法。然后我們常用的兩個間接實現(xiàn)類ArrayList和HashSet中的iterator方法就給我們具體構(gòu)造并返回了一個迭代器對象。
我們找到ArrayList類,查看iterator方法的實現(xiàn)。

@Override
public Iterator iterator() {
    return new ArrayListIterator();
}

ArrayListIterator類型定義如下:

private class ArrayListIterator implements Iterator {
    /** Number of elements remaining in this iteration */
    private int remaining = size;

    /** Index of element that remove() would remove, or -1 if no such elt */
    private int removalIndex = -1;

    /** The expected modCount value */
    private int expectedModCount = modCount;

    public boolean hasNext() {
        return remaining != 0;
    }

    @SuppressWarnings("unchecked") public E next() {
        ArrayList ourList = ArrayList.this;
        int rem = remaining;
        if (ourList.modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
        if (rem == 0) {
            throw new NoSuchElementException();
        }
        remaining = rem - 1;
        return (E) ourList.array[removalIndex = ourList.size - rem];
    }

    public void remove() {
        Object[] a = array;
        int removalIdx = removalIndex;
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
        if (removalIdx < 0) {
            throw new IllegalStateException();
        }
        System.arraycopy(a, removalIdx + 1, a, removalIdx, remaining);
        a[--size] = null;  // Prevent memory leak
        removalIndex = -1;
        expectedModCount = ++modCount;
    }
}

我們看到這個類實現(xiàn)了Iterator接口,接口的定義如下:

public interface Iterator {

    boolean hasNext();

    E next();

    default void remove() {
        throw new UnsupportedOperationException("remove");
    }

    default void forEachRemaining(Consumer action) {
        Objects.requireNonNull(action);
        while (hasNext())
            action.accept(next());
    }
}

基本的結(jié)構(gòu)也分析完了,接下來對號入座,看一看具體是如何實現(xiàn)工廠方法模式的。
Iterator————>Product ArrayListIteratorr————>ConcreteProduct
Iterable/List————>Factory ArrayList————>ConcreteFactory
工廠方法使一個類的實例化延遲到子類,對應(yīng)著將迭代器Iterator的創(chuàng)建從List延遲到了ArrayList。這就是工廠方法模式。

重構(gòu)

暫無

抽象工廠模式

定義

為創(chuàng)建一組相關(guān)或者是相互依賴的對象提供一個接口,而不需要制定他們的具體類
抽象工廠模式是指當有多個抽象角色時,使用的一種工廠模式。抽象工廠模式可以向客戶端提供一個接口,使客戶端在不必指定產(chǎn)品的具體情況下,創(chuàng)建多個產(chǎn)品族中的產(chǎn)品對象。

示例

public abstract class AbstractProductA{
    public abstract void method();
}
public abstract class AbstractProdectB{
    public abstract void method();
}

public class ConcreteProductA1 extends AbstractProductA{
    public void method(){
        System.out.println("具體產(chǎn)品A1的方法!");
    }
}
public class ConcreteProductA2 extends AbstractProductA{
    public void method(){
        System.out.println("具體產(chǎn)品A2的方法!");
    }
}
public class ConcreteProductB1 extends AbstractProductB{
    public void method(){
        System.out.println("具體產(chǎn)品B1的方法!");
    }
}
public class ConcreteProductB2 extends AbstractProductB{
    public void method(){
        System.out.println("具體產(chǎn)品B2的方法!");
    }
}

public abstract class AbstractFactory{
    public abstract AbstractProductA createProductA();

    public abstract AbstractProductB createProductB();
}

public  class ConcreteFactory1 extends AbstractFactory{
    public  AbstractProductA createProductA(){
        return new ConcreteProductA1();
    }

    public  AbstractProductB createProductB(){
        return new ConcreteProductB1();
    }
}

public  class ConcreteFactory2 extends AbstractFactory{
    public  AbstractProductA createProductA(){
        return new ConcreteProductA2();
    }

    public  AbstractProductB createProductB(){
        return new ConcreteProductB2();
    }
}

Android

由于該模式存在的局限性,Android中很少有用到這個模式的地方,com.android.internal.policy包下的IPolicy有使用到這個模式,它是關(guān)于Android窗口,窗口管理,布局加載,以及事件回退Handler這一系列窗口相關(guān)產(chǎn)品的抽象工廠,但是其在源碼中其實也只有一個具體的工廠實現(xiàn)。因為這部分結(jié)構(gòu)較為復(fù)雜,代碼量大,有興趣的同學(xué)可以自己去查看相關(guān)資料或者閱讀源碼。

與工廠方法模式對比

使用

  • 不依賴于產(chǎn)品類實例如何被創(chuàng)建,組合和表達的細節(jié);
  • 產(chǎn)品有多于一個的產(chǎn)品族,而系統(tǒng)只消費其中某一族的產(chǎn)品;
  • 同屬于同一個產(chǎn)品族是在一起使用的;
  • 提供一個產(chǎn)品類的庫,所有產(chǎn)品以同樣的接口出現(xiàn),從而使使用者不依賴于實現(xiàn);

區(qū)別

  • 抽象工廠是面向一個工廠方法的升級;
  • 抽象方法提供的是一個產(chǎn)品族,即多個產(chǎn)品等級結(jié)構(gòu),而工廠方法則是針對一個產(chǎn)品等級結(jié)構(gòu);
  • 抽象方法提供的產(chǎn)品是衍生自多個抽象或者接口,而工廠方法則衍生自同一個抽象或者接口;

優(yōu)點

  • 抽象工廠模式隔離了具體類的生產(chǎn),使得客戶并不需要知道什么被創(chuàng)建。
  • 當一個產(chǎn)品族中的多個對象被設(shè)計成一起工作時,它能保證客戶端始終只使用同一個產(chǎn)品族中的對象。
  • 增加新的具體工廠和產(chǎn)品族很方便,無須修改已有系統(tǒng),符合“開閉原則”。

缺點

  • 增加新的產(chǎn)品等級結(jié)構(gòu)很復(fù)雜,需要修改抽象工廠和所有的具體工廠類,對“開閉原則”的支持呈現(xiàn)傾斜性。
  • (可以把示例中的AB當做等級,12當做族群,A1B1屬于同一族群不同等級,當添加同一等級下新的產(chǎn)品時很方便,但是要添加不同等級的產(chǎn)品就會破壞“開閉原則”)

由于抽象工廠不易于拓展新的產(chǎn)品族,所以這種設(shè)計模式,在提供對外部人員訪問時,很少使用,也有人說抽象工廠方法模式是一種很“惡心”的設(shè)計模式,運用最為典范的一個是該模式最初的目的,也就是為了適應(yīng)Unit和Windows兩個操作系統(tǒng)下的視圖而構(gòu)建視圖族,視圖族有各自不同的實現(xiàn);另一個就是Java連接數(shù)據(jù)庫的操作中,對不同的數(shù)據(jù)庫的操作而形成的的對象操作族,但是當再次更換數(shù)據(jù)時,所需要造成的接口的修改也十分麻煩,所以擴展性不好

重構(gòu)

暫無

策略模式

定義

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

示例

public abstract class BaseAdvertManager {
    protected abstract void doLoadAdvert();
}

public class FacebookAdvertManager extends BaseAdvertManager {
 @Override
    protected void doLoadAdvert() {
        Log.v(TAG, "加載Facebook廣告");
    }
}

public class AdmobAdvertManager extends BaseAdvertManager {
 @Override
    protected void doLoadAdvert() {
        Log.v(TAG, "加載Admob廣告");
    }
}

Android

Android在屬性動畫中使用時間插值器的時候就用到了策略模式。在使用動畫時,你可以選擇線性插值器LinearInterpolator、加速減速插值器AccelerateDecelerateInterpolator、減速插值器DecelerateInterpolator以及自定義的插值器。這些插值器都是實現(xiàn)根據(jù)時間流逝的百分比來計算出當前屬性值改變的百分比。通過根據(jù)需要選擇不同的插值器,實現(xiàn)不同的動畫效果。

重構(gòu)

暫無

狀態(tài)模式

定義

狀態(tài)模式中,行為是由狀態(tài)來決定的,不同狀態(tài)下有不同行為。狀態(tài)模式和策略模式的結(jié)構(gòu)幾乎是一模一樣的,主要是他們表達的目的和本質(zhì)是不同。

示例

public interface TvState{
    public void nextChannerl();
    public void prevChannerl();
    public void turnUp();
    public void turnDown();
}

public class PowerOffState implements TvState{
    public void nextChannel(){}
    public void prevChannel(){}
    public void turnUp(){}
    public void turnDown(){}

}

public class PowerOnState implements TvState{
    public void nextChannel(){
        System.out.println("下一頻道");
    }
    public void prevChannel(){
        System.out.println("上一頻道");
    }
    public void turnUp(){
        System.out.println("調(diào)高音量");
    }
    public void turnDown(){
        System.out.println("調(diào)低音量");
    }

}

public interface PowerController{
    public void powerOn();
    public void powerOff();
}

public class TvController implements PowerController{
    TvState mTvState;
    public void setTvState(TvStete tvState){
        mTvState=tvState;
    }
    public void powerOn(){
        setTvState(new PowerOnState());
        System.out.println("開機啦");
    }
    public void powerOff(){
        setTvState(new PowerOffState());
        System.out.println("關(guān)機啦");
    }
    public void nextChannel(){
        mTvState.nextChannel();
    }
    public void prevChannel(){
        mTvState.prevChannel();
    }
    public void turnUp(){
        mTvState.turnUp();
    }
    public void turnDown(){
        mTvState.turnDown();
    }
}

public class Client{
    public static void main(String[] args){
        TvController tvController=new TvController();
        tvController.powerOn();
        tvController.nextChannel();
        tvController.turnUp();

        tvController.powerOff();
        //調(diào)高音量,此時不會生效
        tvController.turnUp();
    }
}

Android

Android源碼中很多地方都有用到狀態(tài)模式,舉一個例子,就是Android的WIFI管理模塊。當WIFI開啟時,自動掃描周圍的接入點,然后以列表的形式展示;當wifi關(guān)閉時則清空。這里wifi管理模塊就是根據(jù)不同的狀態(tài)執(zhí)行不同的行為。

與策略模式的區(qū)別

狀態(tài)模式的行為是平行的、不可替換的,策略模式是屬于對象的行為模式,其行為是彼此獨立可相互替換的。

重構(gòu)

項目中有需要功能如瘦臉等存在開關(guān),現(xiàn)在是通過配置文件進行判斷,可以通過狀態(tài)模式進行重構(gòu),進而在具體處理圖片時可以利用多態(tài)的特性直接使用對象進行處理

責任鏈模式

定義

使多個對象都有機會處理請求,從而避免請求的發(fā)送者和接受者直接的耦合關(guān)系,將這些對象連成一條鏈,并沿這條鏈傳遞該請求,直到有對象處理它為止。

示例

/**  * 抽象處理者  */
public abstract class Handler {

    /**      * 持有后繼的責任對象      */
    protected Handler successor;
    /**      * 示意處理請求的方法,雖然這個示意方法是沒有傳入?yún)?shù)的      * 但實際是可以傳入?yún)?shù)的,根據(jù)具體需要來選擇是否傳遞參數(shù)      */
    public abstract void handleRequest();
    /**      * 取值方法      */
    public Handler getSuccessor() {
        return successor;
    }
    /**      * 賦值方法,設(shè)置后繼的責任對象      */
    public void setSuccessor(Handler successor) {
        this.successor = successor;
    }

}

/**  * 具體處理者  */
public class ConcreteHandler extends Handler {
    /**      * 處理方法,調(diào)用此方法處理請求      */
    @Override     public void handleRequest() {
        /**          * 判斷是否有后繼的責任對象          * 如果有,就轉(zhuǎn)發(fā)請求給后繼的責任對象          * 如果沒有,則處理請求          */
        if(getSuccessor() != null)
        {           
            System.out.println("放過請求");
            getSuccessor().handleRequest();           
        }else
        {           
            System.out.println("處理請求");
        }
    }

}

/**  * 發(fā)起請求的客戶類  */
public class Client {

    public static void main(String[] args) {
        //組裝責任鏈
        Handler handler1 = new ConcreteHandler();
        Handler handler2 = new ConcreteHandler();
        handler1.setSuccessor(handler2);
        //提交請求
        handler1.handleRequest();
    }

}

Android

在Android處理點擊事件時,父View先接收到點擊事件,如果父View不處理則交給子View,把責任依次往下傳遞;還有Java的異常捕獲機制也是責任鏈模式的一種體現(xiàn)

重構(gòu)

暫無

解釋器模式

定義

給定一個語言,定義它的語法,并定義一個解釋器,這個解釋器用于解析語言。

示例

如編寫各種功能模塊的配置文件,然后按照項目定義的配置文件編寫規(guī)則在運行過程中將配置文件加載為配置對象,這個模式在日常項目中應(yīng)該或多或少都會使用到,就不貼出代碼了。

Android

這個用到的地方也不少,其一就是Android的四大組件需要在AndroidManifest.xml中定義,其實AndroidManifest.xml就定義了,等標簽(語句)的屬性以及其子標簽,規(guī)定了具體的使用(語法),通過PackageManagerService(解釋器)進行解析。

重構(gòu)

暫無

命令模式

定義

命令模式將每個請求封裝成一個對象,從而讓用戶使用不同的請求把客戶端參數(shù)化;將請求進行排隊或者記錄請求日志,以及支持可撤銷操作。
舉個例子來理解:當我們點擊“關(guān)機”命令,系統(tǒng)會執(zhí)行一系列操作,比如暫停事件處理、保存系統(tǒng)配置、結(jié)束程序進程、調(diào)用內(nèi)核命令關(guān)閉計算機等等,這些命令封裝從不同的對象,然后放入到隊列中一個個去執(zhí)行,還可以提供撤銷操作。

示例

   public void method() {
        Handler.post(new Runnable() {
            @Override
            public void run() {
                clearCache();
                statics();
                finish();
            }
        });
    }

Android

在Android事件機制中,底層邏輯對事件的轉(zhuǎn)發(fā)處理。每次的按鍵事件會被封裝成NotifyKeyArgs對象,通過InputDispatcher封裝具體的事件操作。還有一個例子就是我們使用的Runnable,我們可以使用它來封裝自己想做的操作,然后交給Handler按順序處理,或者在處理前remove取消掉

重構(gòu)

現(xiàn)在的廣告模塊業(yè)務(wù)邏輯可以進行這種模式的重構(gòu),將廣告拉取、廣告展示等請求都封裝成一個個的對象,放入到一個管理容器中按照一定規(guī)則進行調(diào)用,這樣不僅可以避免在調(diào)用了展示廣告接口的時候正在拉取廣告,進而導(dǎo)致展示次數(shù)丟失的情況,也可以在出現(xiàn)網(wǎng)絡(luò)錯誤等異常情況時可以對一些步驟進行取消。

觀察者模式

定義

有時被稱作發(fā)布/訂閱模式,其定義了一種一對多的依賴關(guān)系,讓多個觀察者對象同時監(jiān)聽某一個主題對象。這個主題對象在狀態(tài)發(fā)生變化時,會通知所有觀察者對象,使它們能夠自動更新自己。

示例

Java的Observable類和Observer接口就是實現(xiàn)了觀察者模式。一個Observer對象監(jiān)視著一個Observable對象的變化,當Observable對象發(fā)生變化時,Observer得到通知,就可以進行相應(yīng)的工作。
感興趣的可以直接去查看兩個類的源碼,這個模式比較常用,就不在這里再貼一次了。

Android

ListView的適配器有個notifyDataSetChange()函數(shù),就是通知ListView的每個Item,數(shù)據(jù)源發(fā)生了變化,各個子Item需要重新刷新一下。

重構(gòu)

比如現(xiàn)在相機選完濾鏡拍照后進入自拍確認頁,這時候如果用戶更換了濾鏡,那么回來的時候應(yīng)該把相機界面的濾鏡替換為最新選擇的濾鏡。目前是在相機界面的onResume函數(shù)里做這個邏輯,但是其實可以把濾鏡抽成一個完整的模塊,然后在模塊內(nèi)部自己實現(xiàn)觀察者模式,這樣一方面把濾鏡的邏輯封裝起來,與外界解耦,也符合Java多用組合的理念

EventBus

EventBus的好處很明顯,可以很方便簡單地實現(xiàn)觀察者模式,但是壞處也很明顯

  • 大量的濫用,將導(dǎo)致邏輯的分散,出現(xiàn)問題后很難定位。
  • 沒辦法實現(xiàn)強類型,在編譯的時候就發(fā)現(xiàn)問題,(Otto實現(xiàn)了這個,但性能有問題)。在實現(xiàn)上通過一個很弱的協(xié)議,比如onEvent{XXX}, {XXX}表示ThreadModel,來實現(xiàn)線程的切換。
  • 代碼可讀性存在問題,IDE無法識別這些協(xié)議,對IDE不友好。

所以如果出現(xiàn)了需要使用觀察者模式的情況,在各方面條件允許的情況下,建議還是在這個模塊中自己實現(xiàn)觀察者模式,如果發(fā)現(xiàn)這個功能在其他模塊也需要,那么就要考慮是不是應(yīng)該把這系列功能抽成一個更加獨立的模塊從而進行復(fù)用,而不是貪圖方便地直接使用EventBus

備忘錄模式

定義

在不破壞封閉的前提下,捕獲一個對象的內(nèi)部狀態(tài),并在對象之外保存這個狀態(tài),這樣,以后就可將對象恢復(fù)到原先保存的狀態(tài)中。

示例

序列化對象到本地并在必要時將對象反序列化恢復(fù)回來

      public PhotoData readPhotoData(String path) {
            PhotoData photoData = null;
            ObjectInputStream objInput = null;
            try {
                objInput = new ObjectInputStream(new FileInputStream(path));
                photoData = (PhotoData) objInput.readObject();
            } catch (IOException | ClassNotFoundException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (objInput != null) {
                        objInput.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return photoData;
        }

    public void writePhotoData(PhotoData data, String path) {
        ObjectOutputStream objOutput = null;
        try {
            objOutput = new ObjectOutputStream(new FileOutputStream(path));
            objOutput.writeObject(data);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (objOutput != null) {
                    objOutput.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

Android

Activity的onSaveInstanceState和onRestoreInstanceState就是用到了備忘錄模式,分別用于保存和恢復(fù)。

重構(gòu)

暫無

迭代器模式

定義

提供一種方法順序訪問一個容器對象中的各個元素,而不需要暴露該對象的內(nèi)部表示。
迭代器模式是與集合共生共死的,一般來說,我們只要實現(xiàn)一個集合,就需要同時提供這個集合的迭代器,就像java中的Collection,List、Set、Map等,這些集合都有自己的迭代器。假如我們要實現(xiàn)一個這樣的新的容器,當然也需要引入迭代器模式,給我們的容器實現(xiàn)一個迭代器。

示例

Java的Iterator就是一個抽象迭代器,通過實現(xiàn)這個接口各個集合可以提供自己定制的具體迭代器,感興趣的可以直接查看源碼
雖然我們使用集合的場景非常多,但是實際使用到迭代器的卻比較少,對于比較簡單的遍歷(像數(shù)組或者有序列表),使用迭代器方式遍歷較為繁瑣,比如ArrayList,我們更傾向于使用for循環(huán)來遍歷,但是針對hash表之類的集合來說,引入迭代器就反而簡單多了。同時我們也可以通過自定義迭代器來對有序列表提供正序遍歷或者倒序遍歷,用戶只需要得到迭代器就可以遍歷了,而不需要關(guān)心具體遍歷算法。

Android

Android源碼中,最典型的就是Cursor用到了迭代器模式,當我們使用SQLiteDatabase的query方法時,返回的就是Cursor對象,之后再通過Cursor去遍歷數(shù)據(jù)

重構(gòu)

暫無

模板方法模式

定義

定義一個操作中的算法框架,而將一些步驟延遲到子類中,使得子類可以不改變一個算法的結(jié)構(gòu)即可重定義該算法的某些特定的步驟。

示例

public abstract class BaseAdvertManager {
    public void loadAdvert(Context context, int type) {
        if (NetUtils.checkNetConnection(context) != NetUtils.OK) {
            return;
        }
        mStateArray.put(type, AdvertConstant.AD_STATE_LOADING);
        doLoadAdvert(context, type);
    }

    protected abstract void doLoadAdvert(Context context, int type);
}

廣告管理器抽象類定義了加載廣告的通用模板,但是又把模板中具體加載廣告的邏輯聲明為抽象方法為各個子類自我實現(xiàn)

Android

啟動一個Activity過程非常復(fù)雜,有很多地方需要開發(fā)者定制,也就是說,整體算法框架是相同的,但是將一些步驟延遲到子類中,比如Activity的onCreate、onStart等等。這樣子類不用改變整體啟動Activity過程即可重定義某些具體的操作了。

重構(gòu)

大部分代碼相同部分代碼不同的方法都可以嘗試使用模板方法重構(gòu),要么是在同一個類里面進行方法的重構(gòu),要么通過塑造模板函數(shù)的重構(gòu)手段對子類與父類進行重構(gòu)
項目中自拍確認頁保存照片并分享與保存照片并后退目前是兩個獨立的方法,但是方法內(nèi)部大多數(shù)代碼都是一樣的,就需要用該模式進行重構(gòu),由于代碼量大而且該重構(gòu)手段比較簡單,就不貼出代碼

訪問者模式

定義

封裝一些作用于某種數(shù)據(jù)結(jié)構(gòu)中各元素的操作,它可以在不改變這個數(shù)據(jù)結(jié)構(gòu)的前提下定義作用于這些元素的新的操作。
假如一個對象中存在著一些與本對象不相干(或者關(guān)系較弱)的操作,為了避免這些操作污染這個對象,則可以使用訪問者模式來把這些操作封裝到訪問者中去。
假如一組對象中,存在著相似的操作,為了避免出現(xiàn)大量重復(fù)的代碼,也可以將這些重復(fù)的操作封裝到訪問者中去。
訪問者模式的目的是封裝一些施加于某種數(shù)據(jù)結(jié)構(gòu)元素之上的操作,一旦這些操作需要修改的話,接受這個操作的數(shù)據(jù)結(jié)構(gòu)則可以保持不變。
訪問者模式是23種設(shè)計模式中最復(fù)雜最難理解的一個,但他的使用率并不高,大部分情況下,我們不需要使用訪問者模式,少數(shù)特定的場景才需要。

大多數(shù)情況下,你并需要使用訪問者模式,但是當你一旦需要使用它時,那你就是真的需要它了?!狦OF《設(shè)計模式:可復(fù)用面向?qū)ο筌浖幕A(chǔ) 》

示例

interface Service {

    public void accept(Visitor visitor);
}

class Draw implements Service {

    public void accept(Visitor visitor) {
        visitor.process(this);
    }
}

class Fund implements Service {

    public void accept(Visitor visitor) {
        visitor.process(this);
    }
}

class Saving implements Service {

    public void accept(Visitor visitor) {
        visitor.process(this);
    }
}

class Visitor {

    public void process(Service service) {
        // 基本業(yè)務(wù)
        System.out.println("基本業(yè)務(wù)");
    }

    public void process(Saving service) {
        // 存款
        System.out.println("存款");
    }

    public void process(Draw service) {
        // 提款
        System.out.println("提款");
    }

    public void process(Fund service) {
        System.out.println("基金");
        // 基金
    }
}

public class Client {
    public static void main(String[] args){
        Service saving = new Saving();
        Service fund = new Fund();
        Service draw = new Draw();

        Visitor visitor = new Visitor();
        saving.accept(visitor);
        fund.accept(visitor);
        draw.accept(visitor);
    }
}

采用Visitor的好處如上面所示,當需要改變其中一項業(yè)務(wù)的處理時,不需要每個地方都進行修改,而只需要改動Visitor類中相應(yīng)的處理函數(shù)就可以了。也就是說它適合于業(yè)務(wù)處理時常發(fā)生變動的情況。
當然,Visitor也有它自身的限制。它不適合于業(yè)務(wù)數(shù)量的經(jīng)常變化,因為一旦新增或刪除一些Service時,需要對Visitor進行相應(yīng)的增刪。也就是說具體Service與Visitor是耦合的。

Android

Android中運用訪問者模式,其實主要是在編譯期注解中,編譯期注解核心原理依賴APT(Annotation Processing Tools),著名的開源庫比如ButterKnife、Dagger、Retrofit都是基于APT。

重構(gòu)

如果是一些經(jīng)常需要變動邏輯的業(yè)務(wù)則非常適合使用訪問者模式,如果是需要頻繁增加新的業(yè)務(wù)的,則不適合,所以Android的UI展示部分其實理論上來說是適合使用訪問者模式的,因為UI常常一個版本一個變化,如果當UI的變化不只是局限在XML中修修改改的話,而是已經(jīng)體現(xiàn)在了代碼中,那么可以考慮是否可以使用訪問者模式進行修改。
目前實際項目中暫無這種情況,廣告模塊后續(xù)的UI渲染由于是根據(jù)不同的廣告平臺所下發(fā)的廣告對象來進行對應(yīng)的渲染,目前每個廣告平臺渲染視圖的接口所需參數(shù)不太一樣,但是可以考慮進行一下抽離封裝,做成一個簡單的Visitor試試看。

中介者模式

定義

中介者模式包裝了一系列對象相互作用的方式,使得這些對象不必相互明顯調(diào)用,從而使他們可以輕松耦合。當某些對象之間的作用發(fā)生改變時,不會立即影響其他的一些對象之間的作用保證這些作用可以彼此獨立的變化,中介者模式將多對多的相互作用轉(zhuǎn)為一對多的相互作用。
其實,中介者對象是將系統(tǒng)從網(wǎng)狀結(jié)構(gòu)轉(zhuǎn)為以調(diào)停者為中心的星型結(jié)構(gòu)。
舉個簡單的例子,一臺電腦包括:CPU、內(nèi)存、顯卡、IO設(shè)備。其實,要啟動一臺計算機,有了CPU和內(nèi)存就夠了。當然,如果你需要連接顯示器顯示畫面,那就得加顯卡,如果你需要存儲數(shù)據(jù),那就要IO設(shè)備,但是這并不是最重要的,它們只是分割開來的普通零件而已,我們需要一樣?xùn)|西把這些零件整合起來,變成一個完整體,這個東西就是主板。主板就是起到中介者的作用,任何兩個模塊之間的通信都會經(jīng)過主板協(xié)調(diào)。

示例

public abstract class Person {
    protected String name;
    protected Mediator mediator;

    Person(String name,Mediator mediator){
        this.name = name;
        this.mediator = mediator;
    }

}

public class HouseOwner extends Person{

    HouseOwner(String name, Mediator mediator) {
        super(name, mediator);
    }

    /**      * @desc 與中介者聯(lián)系      * @param message      * @return void      */
    public void constact(String message){
        mediator.constact(message, this);
    }

    /**      * @desc 獲取信息      * @param message      * @return void      */
    public void getMessage(String message){
        System.out.println("房主:" + name +",獲得信息:" + message);
    }
}

public class Tenant extends Person{

    Tenant(String name, Mediator mediator) {
        super(name, mediator);
    }

    /**      * @desc 與中介者聯(lián)系      * @param message      * @return void      */
    public void constact(String message){
        mediator.constact(message, this);
    }

    /**      * @desc 獲取信息      * @param message      * @return void      */
    public void getMessage(String message){
        System.out.println("租房者:" + name +",獲得信息:" + message);
    }
}

public abstract class Mediator {
    //申明一個聯(lián)絡(luò)方法
    public abstract void constact(String message,Person person);
}

public class MediatorStructure extends Mediator{
    //首先中介結(jié)構(gòu)必須知道所有房主和租房者的信息
    private HouseOwner houseOwner;
    private Tenant tenant;

    public HouseOwner getHouseOwner() {
        return houseOwner;
    }

    public void setHouseOwner(HouseOwner houseOwner) {
        this.houseOwner = houseOwner;
    }

    public Tenant getTenant() {
        return tenant;
    }

    public void setTenant(Tenant tenant) {
        this.tenant = tenant;
    }

    public void constact(String message, Person person) {
        if(person == houseOwner){          //如果是房主,則租房者獲得信息
            tenant.getMessage(message);
        }
        else{       //反正則是房主獲得信息
            houseOwner.getMessage(message);
        }
    }
}

public class Client {
    public static void main(String[] args) {
        //一個房主、一個租房者、一個中介機構(gòu)
        MediatorStructure mediator = new MediatorStructure();

        //房主和租房者只需要知道中介機構(gòu)即可
        HouseOwner houseOwner = new HouseOwner("張三", mediator);
        Tenant tenant = new Tenant("李四", mediator);

        //中介結(jié)構(gòu)要知道房主和租房者
        mediator.setHouseOwner(houseOwner);
        mediator.setTenant(tenant);

        tenant.constact("聽說你那里有三室的房主出租.....");
        houseOwner.constact("是的!請問你需要租嗎?");
    }
}

房主:張三,獲得信息:聽說你那里有三室的房主出租…..
租房者:李四,獲得信息:是的!請問你需要租嗎?

Android

在Binder機制中,就用到了中介者模式。我們知道系統(tǒng)啟動時,各種系統(tǒng)服務(wù)會向ServiceManager提交注冊,即ServiceManager持有各種系統(tǒng)服務(wù)的引用 ,當我們需要獲取系統(tǒng)的Service時,比如ActivityManager、WindowManager等(它們都是Binder),首先是向ServiceManager查詢指定標示符對應(yīng)的Binder,再由ServiceManager返回Binder的引用。并且客戶端和服務(wù)端之間的通信是通過Binder驅(qū)動來實現(xiàn),這里的ServiceManager和Binder驅(qū)動就是中介者。

重構(gòu)

從年初開始就有在項目里面做MVP的重構(gòu),MVP架構(gòu)里面P層其實就是一個中介者,負責協(xié)調(diào)V和M

外觀模式/門面模式

定義

要求一個子系統(tǒng)的外部與其內(nèi)部的通信必須通過一個統(tǒng)一的對象進行。
舉個例子,我們在啟動計算機時,只需按一下開關(guān)鍵,無需關(guān)系里面的磁盤、內(nèi)存、cpu、電源等等這些如何工作,我們只關(guān)心他們幫我啟動好了就行。實際上,由于里面的線路太復(fù)雜,我們也沒辦法去具體了解內(nèi)部電路如何工作。主機提供唯一一個接口“開關(guān)鍵”給用戶就好。

示例

/**  * cpu子系統(tǒng)類  */
public class CPU {
    public static final Logger LOGGER = Logger.getLogger(CPU.class);
    public void start()     {
        LOGGER.info("cpu is start...");
    }

    public void shutDown()     {
        LOGGER.info("CPU is shutDown...");
    }
}

/**  * Disk子系統(tǒng)類  */
public class Disk {
    public static final Logger LOGGER = Logger.getLogger(Disk.class);
    public void start()     {
        LOGGER.info("Disk is start...");
    }

    public void shutDown()     {
        LOGGER.info("Disk is shutDown...");
    }
}

/**  * Memory子系統(tǒng)類  */
public class Memory {
    public static final Logger LOGGER = Logger.getLogger(Memory.class);
    public void start()     {
        LOGGER.info("Memory is start...");
    }

    public void shutDown()     {
        LOGGER.info("Memory is shutDown...");
    }
}

/**  * 門面類(核心)  */
public class Computer {
    public static final Logger LOGGER = Logger.getLogger(Computer.class);

    private CPU cpu;
    private Memory memory;
    private Disk disk;
    public Computer()     {
        cpu = new CPU();
        memory = new Memory();
        disk = new Disk();
    }
    public void start()     {
        LOGGER.info("Computer start begin");
        cpu.start();
        disk.start();
        memory.start();
        LOGGER.info("Computer start end");
    }

    public void shutDown()     {
        LOGGER.info("Computer shutDown begin");
        cpu.shutDown();
        disk.shutDown();
        memory.shutDown();
        LOGGER.info("Computer shutDown end...");
    }
}

/**  * 客戶端類  */
public class Cilent {
    public static final Logger LOGGER = Logger.getLogger(Cilent.class);
    public static void main(String[] args)     {
        Computer computer = new Computer();
        computer.start();
        LOGGER.info("=================");
        computer.shutDown();
    }
}

從上面的實例來看,有了這個Facade類,也就是Computer類,用戶就不用親自去調(diào)用子系統(tǒng)中的Disk,Memory、CPU類了,不需要知道系統(tǒng)內(nèi)部的實現(xiàn)細節(jié),甚至都不用知道系統(tǒng)內(nèi)部的構(gòu)成。客戶端只需要跟Facade交互就可以了。

Android

那么Android哪里使用到了外觀模式呢?依然回到Context,Android內(nèi)部有很多復(fù)雜的功能比如startActivty、sendBroadcast、bindService等等,這些功能內(nèi)部的實現(xiàn)非常復(fù)雜,如果你看了源碼你就能感受得到,但是我們無需關(guān)心它內(nèi)部實現(xiàn)了什么,我們只關(guān)心它幫我們啟動Activity,幫我們發(fā)送了一條廣播,綁定了Activity等等就夠了。

重構(gòu)

暫無

代理模式

定義

給某一個對象提供一個代理,并由代理對象控制對原對象的引用。
代理模式有幾種,虛擬代理,計數(shù)代理,遠程代理,動態(tài)代理。主要分為兩類,靜態(tài)代理和動態(tài)代理。

靜態(tài)代理

定義

靜態(tài)代理比較簡單,是由程序員編寫的代理類,并在程序運行前就編譯好的,而不是由程序動態(tài)產(chǎn)生代理類,這就是所謂的靜態(tài)。可以通過聚合和繼承兩種方式實現(xiàn),繼承方式不夠靈活,所以只介紹聚合的方式

示例

nterface Subject {
    void request();
}

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

class Proxy implements Subject {
    private Subject subject;

    public Proxy(Subject subject){
        this.subject = subject;
    }
    public void request(){
        System.out.println("begin");
        subject.request();
        System.out.println("end");
    }
}

public class ProxyTest {
    public static void
                                                分享題目:談?wù)?3種設(shè)計模式在Android項目中的應(yīng)用                                                
網(wǎng)站URL:http://www.5511xx.com/article/djjjdpj.html