工廠方法模式

echoou發表於2020-12-31

定義

工廠方法模式的作用就是封裝物件的建立,由子類決定要建立的物件是什麼。

適用範圍

工廠方法模式特別適合與需要建立複雜物件的場景

實現

首先可以看一下,工廠方法模式的UML類圖

工廠方法模式

這樣一個圖看起來可能有點暈,下面就結合時下最流行的共享單車,寫一個工廠方法模式的通用模式程式碼。

/**
 * 抽象單車產品
 *簡單起見,單車的製造方式(外觀)和計費方式 作為單車類的兩個方法
 */

public interface Bicycle {
    /**
     * 單車生產方式
     */
    String manufacture();

    /**
     * 單車計費方式
     */
    String billing();
}

/**
 * Bicycle 抽象單車生產工廠
 */

public interface BicycleFactory {

    Bicycle makeBicycle();
}


public class Mobike implements Bicycle {
    @Override
    public String manufacture() {
        System.out.print("摩拜單車---橙色---有定位功能");
        return "摩拜單車---橙色---有定位功能";
    }

    @Override
    public String billing() {
        System.out.print("Mobike每30分鐘收費1元");
        return "Mobike每30分鐘收費1元";
    }
}

public class MobikeFactory implements BicycleFactory {
    @Override
    public Bicycle makeBicycle() {
        return new Mobike();
    }
}

public class Ofo implements Bicycle {
    @Override
    public String manufacture() {
        System.out.print("ofo單車---黃色---密碼不變");
        return "ofo單車---黃色---密碼不變";
    }

    @Override
    public String billing() {
        System.out.print("ofo單車: 師生認證使用者0.5元/小時,非師生使用者1元/小時");
        return "ofo單車: 師生認證使用者0.5元/小時,非師生使用者1元/小時";
    }
}

public class OfoFactory implements BicycleFactory {
    @Override
    public Bicycle makeBicycle() {
        return new Ofo();
    }
}複製程式碼

在上面的程式碼中:

  • Bicycle 抽象產品
  • Mobike 和 Ofo 具體產品
  • BicycleFactory 抽象工廠
  • MobikeFactory 和 OfoFactory 具體的工廠

這就是工廠模式。所有的產品(Mobike和Ofo)有共同的父類 Bicycle,而每一個產品又有各自的工廠(MobikeFactory和
OfoFactory)去負責建立自己;當然這裡所有的產品可以有公共的工廠,在公共的工廠裡通過引數負責生成不同的產品。如下方式:

/**
 * 所有產品共用一個工廠
 */
public class CommonFactory {
    public static Bicycle makeBicycle(String type) {
        switch (type) {
            case "mobike":
                return new Mobike();
            case "ofo":
                return new Ofo();
            default:
                return null;

        }

    }
}複製程式碼

個人感覺,每個產品使用各自的工廠是一種更有設計模式的做法,也就是更符合開閉原則;如果有了新產品,就不必去修改原有的工廠,增加新的產品和工廠即可。

有個工廠,就非常方便我們去建立不同的物件了。

public class FactoryPatternActivity extends AppCompatActivity {
    private TextView bike_result;
    private BicycleFactory factory;
    private Bicycle mBicycle;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_factory_pattern);
        bike_result = V.f(this, R.id.bike_result);
    }


    public void MobikeClick(View view) {
        factory = new MobikeFactory();
        mBicycle = factory.makeBicycle();
        updateView(mBicycle);
    }

    public void OfoClick(View view) {
        factory = new OfoFactory();
        mBicycle = factory.makeBicycle();
        updateView(mBicycle);
    }
    private void updateView(Bicycle mBicycle) {
        bike_result.setText("");
        StringBuilder sb = new StringBuilder();
        sb.append(mBicycle.manufacture())
                .append("\n")
                .append(mBicycle.billing());
        bike_result.setText(sb.toString());
    }
}複製程式碼

在這裡使用工廠模式,BicycleFactory 封裝了Bicycle 物件具體生成的過程;當需要具體的物件時,呼叫每個物件各自的工廠生成物件即可。試想,如果沒有使用工廠模式,那麼這裡FactoryPatternActivity 將包含大量的程式碼去負責建立複雜的Bicycle物件,但是從MVP的角度來說,這是完全不屬於Activity(View)的工作。

Android 中的Factory

BitmapFactory

在Android 系統中,說道Factory大家第一個想到的可能就是BitmapFactory了。研究過Bitmap的同學應該清楚,BitmapFactory 為了方便開發者,提供了一系列的方法方便大家通過各種途徑建立Bitmap。

工廠方法模式

這裡可以看一下decodeStream(InputStream is) 方法:

    public static Bitmap decodeStream(InputStream is) {
        return decodeStream(is, null, null);
    }複製程式碼

可以看到,這裡又會去呼叫別的方法;最終上述的所有方法,殊途同歸都會呼叫到一些native的方法去真正的完成Bitmap的建立。其實按照上面的UML圖來說,嚴格來說BitmapFactory 的實現並不是工廠方法模式;只能說是簡單工廠。在BitmapFactory類中對於唯一的產品Bitmap只有唯一的工廠BitmapFactory,它所有的生產方法都是靜態的;如果要新增一種生產Bitmap的方式,就得修改唯一的工廠(BitmapFactory)。因此,從設計模式的角度來說,完全不符合開閉原則。

這裡並不是說BitmapFactory這個類的寫法不好,只是剛好從工廠方法模式的角度找了一個大家熟悉的類做了一個分析,Android系統的程式碼其實寫的很好。BitmapFactory 這個類裡包含的方法已經夠大家使用,因此它設計成這個樣子是完全合理的。

onCreate 方法

《Android 原始碼設計模式解析於實戰》這本書中提到 onCreate 方法是的實現可以說是工廠模式,的確從廣義角度來說,通過不同的引數(R.layout.acitity) 建立出了不同的View;的確是可以算是工廠模式。至於具體程式碼的實現邏輯,這裡就不拾人牙慧了。

總結

總的來說,工廠模式就是種瓜得瓜,種豆得豆;根據不同的輸入建立不同型別的物件。通過上面的例項其實可以總結出規律,當我們在程式碼中寫了很多if-else或者是switch時,是不是可以考慮以下使用工廠模式,也許我們就是在建立不通過的物件,也許只是自己沒有發現。


工廠方法模式真的感覺只能意會,不能言傳。看別人寫的東西總是忘掉,這樣自己寫一遍才算理解了。

相關文章