設計模式--靜態工廠、簡單工廠方法案例分析

簡介

1.學習本篇文章,瞭解簡單工廠設計模式的使用場景。
2.如何使用簡單工廠模式。
3.簡單工廠模式能解決什麼問題?java

場景

如今有一家外賣小店須要從生產一份外賣開始進行考慮設計,當客戶在網上點出不一樣味道的菜時,外賣小店就將按照不一樣的訂單進行生產出菜品,而後進行打包、等待外賣小哥獲取、贈送給客戶等不一樣的幾道工序,纔算完成一單,可是後期因爲生意很好,客戶評價很高,有些地方的老闆想加盟本店了,那麼可能就會出現不一樣味道的菜單,還有一些本地的特點菜也會加上菜單,這時,客戶就能點到更多的菜品了,爲了達到某些商家快速並且合理的進行管理,你是怎麼設計這個方案的呢?git

分析

通常狀況下客戶點餐的時候,都會查看平分高低,還有出貨次數,若是人氣好的,確定要大量生產,而沒有人點的,則能夠考慮去除,因此咱們經過以上的考慮,須要封裝建立對象的代碼,如將生產商品的對象封裝起來,這樣,咱們出掉或者添加的時候,都只修改這部分的代碼,那麼是哪一個生產商品呢?答案確定是店家了,因此咱們稱這個生產商品的店家爲「工廠」。
接下來咱們進行分析以上代碼該如何展示出來呢?咱們將經過兩種方式來進行編寫。github

靜態工廠模式

如何實現呢?咱們先來看看本例的類圖編程

static_factory.png

1.建立一個美食店,MealStore.class設計模式

/**
 * Author Eirunye
 * Created by on 2018/9/19.
 * Describe
 */
public class MealStore {


    public Meal submitOrderMeal(String type) {

        Meal meal;
        //利用靜態工廠方法生成產品
        //重點(靜態工廠實現代碼)
        meal = SimpleMealsFactory.createMeal(type);

        //如下方法是進行一些設計而已不是靜態工廠方法的模塊,是產品的一些操做而已,可有可無的
        //店家準備中...
        meal.mealPreparation();
        //打包
        meal.bake();
        //獲取
        meal.getMeal();
        //配送
        meal.send();

        return meal;
    }
}

2.建立一個靜態工廠SimpleMealsFactory.classide

/**
 * Author Eirunye
 * Created by on 2018/9/18.
 * Describe 創建一個簡單靜態工廠,該工廠生產不一樣的菜品(美食)
 * Tip: 提示:這是否是咱們常用的Util類的編寫方式?
 */
public class SimpleMealsFactory {

    //將生產產品(美食放在這裏)
    public static Meal createMeal(String type) {

        Meal meal = null;

        if ("crayfish".equals(type)) {
            meal = new CrayfishMeal(); //建立什麼類型的產品(美食)讓子類來操做
        } else if ("roastChicken".equals(type)) {
            meal = new RoastChicken();
        } else if ("A".equals(type)) {
         
        } else if ("B".equals(type)) {

        }
        // ...
        return meal; //返回的是美食商品
    }
}

3.建立產品美食抽象基類Meal.class,這樣的話咱們就能夠交給子類來完成商品的生產。學習

/**
 * Author Eirunye
 * Created by on 2018/9/19.
 * Describe  定義一個抽象產品接口、這裏也能夠是抽象類
 */
public abstract class Meal {
public List mealInfo = new ArrayList();

    public void mealPreparation() {
        System.out.println("您的商品準備中..."+this.name);
        System.out.println("adding material...");
        System.out.println("adding  condiment...");
        System.out.println("adding mealInfo...");

        for (int i = 0, len = mealInfo.size(); i < len; i++) {
            System.out.println(" [" + mealInfo.get(i) + "]");
        }
    }
    public void bake() {
        System.out.println("進行打包,只需1分鐘就能打包完成!");
    }
    public void getMeal() {
        System.out.println("外賣小哥獲取美食,外賣小哥可能須要花費1~20分鐘來獲取美食!");
    }
    public void send() {
        System.out.println("配送給客戶,配送須要大概5~40分鐘送達!");
    }
}

4.這裏模擬具體產品,必須去實現Meal接口或者去派生該抽象類,以下小龍蝦美食:CrayfishMeal.class測試

/**
 * Author Eirunye
 * Created by on 2018/9/19.
 * Describe 模擬產品(具體的美食--小龍蝦)
 */
public class CrayfishMeal extends Meal {
    public CrayfishMeal() {
        setName("香辣小龍蝦.....");
        setMaterial("添加5份小龍蝦...");
        setCondiment("添加適量的調味品...");
        mealInfo.add("生成可口的小龍蝦...");
    }
}

5.測試動畫

/**
 * Author Eirunye
 * Created by on 2018/9/19.
 * Describe
 */
public class Test {
    public static void main(String[] args) {

        //建立一個工廠類(即商品總店)
        MealStore mealStore = new MealStore();
       //這裏咱們要傳遞在靜態工廠實例定義的字符串,不然將報空指針。
        mealStore.submitOrderMeal("roastChicken");
    }
}

輸出結果:this

"C:\Program Files\Java\jdk1.8.0_161\bin\java"...

您的商品準備中...燒雞.....
adding material...
adding  condiment...
adding mealInfo...
 [生成可口的燒雞...]
進行打包,只需1分鐘就能打包完成!
外賣小哥獲取美食,外賣小哥可能須要花費1~20分鐘來獲取美食!
配送給客戶,配送須要大概5~40分鐘送達!

Process finished with exit code 0
  • 注:

首先咱們將生產商品建立放在了靜態工廠中,靜態工廠處理對象建立的細節,MealStore 美食店只關心如何獲得美食商品就能夠了,並進行打包、獲取、派送等操做,而這樣操做起來方便了產品的建立了。

簡單工廠方法

咱們經過靜態工廠方法的方式實現了該功能,可是,是否有更好的封裝方式呢?接下來咱們來分析一下吧。本例類圖關係

funtion_factory.png

1.如今咱們將MealStore.class,修改成抽象類,而且將生產商品的方法也修改成抽象方法,咱們這樣作的目的,爲何呢?
咱們這樣作是讓各個分店子類來實現商品的生產,擴展性更高,封裝性更加完善,而該抽象類並不知道是哪一個子類來完成商品的建立,達到了耦合。代碼以下:

/**
 * Author Eirunye
 * Created by on 2018/9/18.
 * Describe 抽象工廠基類 美食總店
 */
public abstract class MealStore {

    /**
     * 客戶下單
     *
     * @param type 選擇什麼樣的美食
     * @return 美食 Meal
     */
    public Meal submitOrderMeal(String type) {

        Meal meal;

        //這裏是咱們將生產的美食
        meal = createMeal(type);

        //店家準備中...
        meal.mealPreparation();
        //打包
        meal.bake();
        //獲取
        meal.getMeal();
        //配送
        meal.send();

        return meal;
    }

    //實現抽象的工廠方法,讓每一個分店來完成今生產操做,
    protected abstract Meal createMeal(String type);
}

2.建立分店子類JiangNanMealStore .class派生自MealStore.class,進行生產商品

/**
 * Author Eirunye
 * Created by on 2018/9/18.
 * Describe  JiangNanMealStore分店,這裏是須要增長修改的地方,可能有新的菜品的時候就在這裏增長或者刪除***
 */
public class JiangNanMealStore extends MealStore {

    @Override
    protected Meal createMeal(String type) {
        return getMeal(type);
    }
   //讓子類來建立產品
    private Meal getMeal(String type) {
        if ("crayfish".equals(type)) {
            return new CrayfishMeal();//小龍蝦
        } else if ("roastDuck".equals(type)) {
            return new RoastDuckMeal();
        } else return null;
    }
}

3.建立商品抽象基類Meal.class

/**
 * Author Eirunye
 * Created by on 2018/9/18.
 * Describe 抽象產品父類 美食抽象類
 */
public abstract class Meal {
public List mealInfo = new ArrayList();

    public void mealPreparation() {
        System.out.println("您的商品準備中..."+this.name);
        System.out.println("adding material...");
        System.out.println("adding  condiment...");
        System.out.println("adding mealInfo...");

        for (int i = 0, len = mealInfo.size(); i < len; i++) {
            System.out.println(" [" + mealInfo.get(i) + "]");
        }
    }
    public void bake() {
        System.out.println("進行打包,只需1分鐘就能打包完成!");
    }
    public void getMeal() {
        System.out.println("外賣小哥獲取美食,外賣小哥可能須要花費1~20分鐘來獲取美食!");
    }
    public void send() {
        System.out.println("配送給客戶,配送須要大概5~40分鐘送達!");
    }
}

3.定義具體子類CrayfishMeal.class產品,擴展自Meal .class

/**
 * Author Eirunye
 * Created by on 2018/9/18.
 * Describe 具體產品 小龍蝦美食
 */
public class CrayfishMeal extends Meal {

    public CrayfishMeal() {
        setName("可口的小龍蝦.....");
        setMaterial("添加幾份小龍蝦+一些材料...");
        setCondiment("添加適量的調味品...");
        mealInfo.add("生成可口的小龍蝦...");
    }
    //這裏重寫了父類的方法
    @Override
    public void bake() {
        System.out.println("小龍蝦分紅5份打包!");
    }
}

4.測試

/**
 * Author Eirunye
 * Created by on 2018/9/18.
 * Describe
 */
public class Test {
    public static void main(String[] args) {
        MealStore jiangNanMealStore = new JiangNanMealStore();
        jiangNanMealStore.submitOrderMeal("crayfish");

        System.out.println("江南店完成一單");
        System.out.println("==============================\n");

        MealStore guangDongMealStore = new GuangDongMealStore();
        guangDongMealStore.submitOrderMeal("roastDuck");

        System.out.println("廣東店完成一單");
    }
}

輸出結果

"C:\Program Files\Java\jdk1.8.0_161\bin\java"...
您的商品準備中...可口的小龍蝦.....
adding material...
adding  condiment...
adding mealInfo...
 [生成可口的小龍蝦...]
小龍蝦分紅5粉打包!
外賣小哥獲取美食,外賣小哥可能須要花費1~20分鐘來獲取美食!
配送給客戶,配送須要大概5~40分鐘送達!
江南店完成一單
==============================

您的商品準備中...江南烤鴨.....
adding material...
adding  condiment...
adding mealInfo...
 [生成可口的烤鴨...]
進行打包,只需1分鐘就能打包完成!
外賣小哥獲取美食,外賣小哥可能須要花費1~20分鐘來獲取美食!
配送給客戶,配送須要大概5~40分鐘送達!
廣東店完成一單

Process finished with exit code 0

下載

本篇案例代碼--碼雲

本篇案例代碼--GitHub

設計模式系列--碼雲

設計模式系列--GitHub

總結

咱們經過簡單的例子瞭解了簡單工廠模式的開發案例,其實,簡單工廠並非咱們常說的23中設計模式,他只是咱們經常使用的一種編程習慣罷了,抽象工廠,纔是咱們經常使用的設計模式,接下來咱們會講解到抽象工廠模式。
靜態工廠(簡單工廠)和簡單工廠方法有什麼不一樣呢?

靜態工廠將生產商品都定義在靜態工廠的方法內,而簡單工廠方法是交給子類來完成。可是靜態工廠(簡單工廠)不具有簡單工廠方法所具備的擴展性強。

簡單工廠方法的子類將會出現大量相同的代碼,可是同時它也能夠重寫分類的方法,完成本身定義操做。
在Android中也經常使用到靜態工廠、或者是工廠方法等編程設計思路,如AnimationUtils類獲取的各個子類的動畫,BitmapFactory等

推薦

你們能夠到個人博客https://eirunye.github.io進行瀏覽相關文章,你們一塊兒相互探討技術。

設計模式系列你們能夠了解相關知識。

相關文章
相關標籤/搜索