简介

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 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 {@Overrideprotected 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("生成可口的小龙虾...");}//这里重写了父类的方法@Overridepublic 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进行浏览相关文章,大家一起相互探讨技术。

设计模式系列大家可以了解相关知识。

设计模式--静态工厂、简单工厂方法案例分析相关推荐

  1. 23种设计模式 -----Day01:简单工厂模式

    目录 前言 1.设计模式(Design pattern)定义 2.为什么要使用设计模式(使用设计模式的意义) 3.设计原则 a.单一职责原则 b.开放封闭原则 c.里氏代换原则 d.迪米特法则 e.依 ...

  2. 设计模式 笔记4 | 简单工厂模式 在源码中的应用 | Calendar 日历 | 源码浅析 | 使用总结 | 建造者模式

    文章目录 一.Calendar 日历类 1.1 内部属性 1.2 设置时间属性值 1.3 获取时间属性 1.4 使用 Calander 计算时间 二.Calender 类中的设计模式 2.1 简单工厂 ...

  3. 三种引流方法案例分析

    第3课课程笔记 课程主题:三种引流方法&案例分析 课程题纲: 第一节:58同城引流方法详解(图文并茂) :宠物引流的第二种方法(资料收集与分享) :第三种最高端的玩法(让客户百分百信任你) 正 ...

  4. 【设计模式】Unity3D 简单工厂、工厂(方法)、抽象工厂模式

    创建型模式-工厂三兄弟 提示:个人学习总结,如有错误,敬请指正 文章目录 创建型模式---工厂三兄弟 一.简单工厂模式 1.简单工厂模式是什么? 2.UML图 3.实现方式 二.工厂(方法)模式 1. ...

  5. 【设计模式实战】简单工厂、工厂方法、抽象工厂:原理篇

    小明开发的应用,经常要从XML或者Asset中读取省市区数据. 小明是这样写的: public abstract class IOHandler {/*** 添加*/public abstract v ...

  6. Java描述设计模式(02):简单工厂模式

    一.生活场景简介 1.引入场景 订餐流程简单描述 1).食品抽象类,规定食品的基础属性操作 2).鱼类,鸡肉类食品类扩展 3).订餐流程类,根据食品名称,加工指定类型食品 4).模拟客户端预定操作 2 ...

  7. Java啤酒生产系统描述_Java描述设计模式(02):简单工厂模式

    一.生活场景简介 1.引入场景 订餐流程简单描述 1).食品抽象类,规定食品的基础属性操作 2).鱼类,鸡肉类食品类扩展 3).订餐流程类,根据食品名称,加工指定类型食品 4).模拟客户端预定操作 2 ...

  8. 设计模式-创建型-工厂-简单工厂模式

    一.姑且用一个这样的图表示一下:  二.简单工厂的基本简介:百度释义:又叫静态工厂方法,不属于那23种设计模式之一. 动态决定哪个类被实例化,不必事先知道哪个类要被实例化! 三.举例:QQ里面常用发表 ...

  9. 手撕设计模式之「简单工厂模式」(Java描述)

    前言 利用简单工厂模式可以实现对象创建和业务逻辑处理的分离,但存在工厂类职责过重,增添新产品违背开闭原则等问题.它不属于GoF 23种设计模式之一,但是它可以作为学习工厂方法模式前的一个很好的引导. ...

最新文章

  1. linux shell (()) 双括号运算符使用
  2. android 4.4从图库选择图片,安卓6.0,从系统图库选择照片,裁剪,并显示的问题。...
  3. map:map是否为空?元素数量?删除元素?
  4. 终于有人把机器学习中的评价指标讲清楚了
  5. 计算机一级上机考试试题题库,2016年计算机一级上机考试题库
  6. Python——assert(断言函数)
  7. 行程单图片python预处理_GCC编译过程(预处理-gt;编译-gt;汇编-gt;链接)
  8. Stop Googling!
  9. 面试指南(二):想跳槽,这些技术点你会了吗?
  10. 分段式多级离心泵_D型卧式多级泵结构组成及工作原理
  11. extjs 兼容性问题解决方案
  12. 重装linux后没声音,安装虚拟机后没声音了
  13. 如何测量智能产品的AI智商水平,论AI的三种智商
  14. java使用JSON-RPC进行BTC、LTC钱包开发
  15. js解决键盘长按输入时会有停顿的问题
  16. uo和o的区别和用法_拼音o与uo如何区别使用
  17. MFC CList使用
  18. Zephyr events
  19. sql镜像备份 转 浪客 博客
  20. 多线程:模仿火车站售票

热门文章

  1. 数字音乐生财:月入10万不是梦
  2. KNIME + Python = 数据分析+报表全流程
  3. 我的世界bc端mysql_[BC端简介] BungeeCord跨服群组简介
  4. CSAPP_Chapter1
  5. endcap和welltap_ICC布局规划
  6. 【完全背包】A005_LC_贴纸拼词(dp + 状态压缩)
  7. 中国劳动力动态调查数据(CLDS)2011-2018年
  8. sysvinit源码分析 Linux-init-process-analyse
  9. 新月音标_又一个新月?
  10. BD-Rate和BD-PSNR