简介
1.学习本篇文章,了解简单工厂设计模式的使用场景。
2.如何使用简单工厂模式。
3.简单工厂模式能解决什么问题?
现在有一家外卖小店需要从生产一份外卖开始进行考虑设计,当客户在网上点出不同味道的菜时,外卖小店就将按照不同的订单进行生产出菜品,然后进行打包、等待外卖小哥获取、赠送给客户等不同的几道工序,才算完成一单,但是后期由于生意很好,客户评价很高,有些地方的老板想加盟本店了,那么可能就会出现不同味道的菜单,还有一些本地的特色菜也会加上菜单,这时,客户就能点到更多的菜品了,为了达到某些商家快速而且合理的进行管理,你是怎么设计这个方案的呢?
分析一般情况下客户点餐的时候,都会查看平分高低,还有出货次数,如果人气好的,肯定要大量生产,而没有人点的,则可以考虑去除,所以我们通过以上的考虑,需要封装创建对象的代码,如将生产商品的对象封装起来,这样,我们出掉或者添加的时候,都只修改这部分的代码,那么是哪个生产商品呢?答案肯定是店家了,所以我们称这个生产商品的店家为“工厂”。
接下来我们进行分析以上代码该如何展现出来呢?我们将通过两种方式来进行编写。
如何实现呢?我们先来看看本例的类图
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
/** * 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"); } }
输出结果:
"C:Program FilesJavajdk1.8.0_161injava"... 您的商品准备中...烧鸡..... 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("============================== "); MealStore guangDongMealStore = new GuangDongMealStore(); guangDongMealStore.submitOrderMeal("roastDuck"); System.out.println("广东店完成一单"); } }
输出结果
"C:Program FilesJavajdk1.8.0_161injava"... 您的商品准备中...可口的小龙虾..... 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进行浏览相关文章,大家一起相互探讨技术。
设计模式系列大家可以了解相关知识。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/77287.html
摘要:一简单工厂定义简单工厂其实并不属于种设计模式之一,该模式是工厂方法模式的弱化或者说是工厂方法模式的一种特例,因为简单,所以称为简单工厂模式,也叫做静态工厂模式。 一、简单工厂 定义 简单工厂其实并不属于23种GOF设计模式之一,该模式是工厂方法模式的弱化(或者说是工厂方法模式的一种特例),因为简单,所以称为简单工厂模式(Simple Factory Pattern),也叫做静态工厂模式...
摘要:工厂模式使一个类的实例化延迟到其子类。参考系列源地址系列目录设计模式概述设计模式一简单工厂模式设计模式二工厂方法模式设计模式三抽象工厂模式设计模式四单例模式 一、什么是简单工厂模式 简单工厂 (Simple Factory)又称静态工厂方法模式(Static Factory Method Pattern) 使用的频率可以说是非常之高,它的官方解释为:定义一个用于创建对象的接口,让子...
摘要:基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。工厂方法模式之所以又被称为多态工厂模式,是因为所有的具体工厂类都具有同一抽象父类。工厂方法模式总结工厂方法模式是简单工厂模式的进一步抽象和推广。 JavaScript工厂模式 首先需要说一下工厂模式。工厂模式根据抽象程度的不同分为三种 简单工厂模式 工厂方法模式 抽象工厂模式 1.简单工厂模式 简单工厂模式:又称为静态工厂方法...
摘要:缺点需要慎重考虑是否增加工厂类进行管理,因为会增加代码的复杂度使用场景工厂模式是创建型模式的一种,其实就等价于对象,但是否将对象改造成工厂模式,使我们需要衡量的。 前言 最近北京天气越来越冷了,同在北京的小伙伴大家注意保暖。不扯废话了,让我们直接进入到工厂模式的学习. 什么是工厂模式 定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到子类。 UML类图...
摘要:写在前面一些关于自己在代码设计思维方面的学习记录面向对象的一些理解实例代码就不上了就写一些总结封装提供属性和方法的权限管理只对外暴露接口具体的功能在内部实现继承子类继承父类的方法和属性可以抽离公共代码减少代码冗余多态同一个接口在子类中的不同 写在前面: 一些关于自己在代码设计思维方面的学习记录 面向对象的一些理解 实例代码就不上了, 就写一些总结 封装: 提供属性和方法的权限管理, ...
阅读 1855·2021-09-28 09:36
阅读 2344·2021-09-08 09:35
阅读 3051·2019-08-30 15:53
阅读 1534·2019-08-30 14:08
阅读 644·2019-08-29 18:40
阅读 2821·2019-08-29 13:57
阅读 2684·2019-08-29 13:55
阅读 662·2019-08-26 13:45