1.學習本篇文章,瞭解簡單工廠設計模式的使用場景。
2.如何使用簡單工廠模式。
3.簡單工廠模式能解決什麼問題?java
如今有一家外賣小店須要從生產一份外賣開始進行考慮設計,當客戶在網上點出不一樣味道的菜時,外賣小店就將按照不一樣的訂單進行生產出菜品,而後進行打包、等待外賣小哥獲取、贈送給客戶等不一樣的幾道工序,纔算完成一單,可是後期因爲生意很好,客戶評價很高,有些地方的老闆想加盟本店了,那麼可能就會出現不一樣味道的菜單,還有一些本地的特點菜也會加上菜單,這時,客戶就能點到更多的菜品了,爲了達到某些商家快速並且合理的進行管理,你是怎麼設計這個方案的呢?git
通常狀況下客戶點餐的時候,都會查看平分高低,還有出貨次數,若是人氣好的,確定要大量生產,而沒有人點的,則能夠考慮去除,因此咱們經過以上的考慮,須要封裝建立對象的代碼,如將生產商品的對象封裝起來,這樣,咱們出掉或者添加的時候,都只修改這部分的代碼,那麼是哪一個生產商品呢?答案確定是店家了,因此咱們稱這個生產商品的店家爲「工廠」。
接下來咱們進行分析以上代碼該如何展示出來呢?咱們將經過兩種方式來進行編寫。github
如何實現呢?咱們先來看看本例的類圖編程
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.class
ide
/** * 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 美食店只關心如何獲得美食商品就能夠了,並進行打包、獲取、派送等操做,而這樣操做起來方便了產品的建立了。
咱們經過靜態工廠方法的方式實現了該功能,可是,是否有更好的封裝方式呢?接下來咱們來分析一下吧。本例類圖關係
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
咱們經過簡單的例子瞭解了簡單工廠模式的開發案例,其實,簡單工廠並非咱們常說的23中設計模式,他只是咱們經常使用的一種編程習慣罷了,抽象工廠,纔是咱們經常使用的設計模式,接下來咱們會講解到抽象工廠模式。
靜態工廠(簡單工廠)和簡單工廠方法有什麼不一樣呢?
靜態工廠將生產商品都定義在靜態工廠的方法內,而簡單工廠方法是交給子類來完成。可是靜態工廠(簡單工廠)不具有簡單工廠方法所具備的擴展性強。
簡單工廠方法的子類將會出現大量相同的代碼,可是同時它也能夠重寫分類的方法,完成本身定義操做。
在Android中也經常使用到靜態工廠、或者是工廠方法等編程設計思路,如AnimationUtils類獲取的各個子類的動畫,BitmapFactory等
你們能夠到個人博客https://eirunye.github.io進行瀏覽相關文章,你們一塊兒相互探討技術。
設計模式系列你們能夠了解相關知識。