工厂模式有啥用啊,我的项目没使用工厂模式也照样运行

这是我听过最令人哭笑不得的吐槽,这个程序猿的头发不知道有没有被自己薅秃

的确,项目中不使用工厂模式并不会影响项目的运行

但是,当项目后期需要二次开发时,代码的维护和修改的复杂度,绝对能让你恨不得把自己头发都薅秃

下面我们就来盘一盘工厂模式能解决哪些问题

简单工厂模式

实际案例

假如客户有这样一个需求,做一个用户订购手机来玩游戏的项目

项目中可以生产华为和小米的手机,生产的手机只能用来玩游戏,用户可以通过京东和淘宝来订购手机

需求中的一个前置条件是手机只能用来玩游戏,不能做别的事情。这就类似于一个规范,所有的手机都要遵守这个规范。

制定规范是java中接口的特性,所以我们要定义一个接口基类,叫做Phone,里面有一个玩游戏的方法play()

还要有华为手机和小米手机的类,分别叫做HuweiXiaomi,这两个手机类要遵循手机只能用来玩游戏这个规范,所以它们要实现Phone类,并完成play()方法

用java代码实现分别如下

phone基类

public interface Phone {void play();
}

华为手机类Huawei

public class Huawei implements Phone {@Overridepublic void play() {System.out.println("华为手机玩游戏");}
}

小米手机类Xiaomi

public class Xiaomi implements Phone {@Overridepublic void play() {System.out.println("小米手机玩游戏");}
}

用户可以通过京东和淘宝来订购手机,所以还要有京东和淘宝的类,分别叫做JingdongTaobao。类里面各有一个订购方法叫做order(),可以根据用户的喜好来订购不同的手机

如果用户喜欢华为则订购华为手机来玩游戏,如果用户喜欢小米则订购小米手机来玩游戏,其他的用户就不能玩游戏

因为京东类和淘宝类的代码逻辑一摸一样,这里只贴一下京东类的代码

public class Jingdong {public void order(String type) {Phone phone = null;if ("huawei".equals(type)) {phone = new Huawei();phone.play();} else if ("xiaomi".equals(type)) {phone = new Xiaomi();phone.play();} else {System.out.println("暂不支持");}}
}

这样我们就实现了客户的需求,而且没有使用任何设计模式。

项目虽然可以完美的运行,但是有一个问题值得我们思考,假如又增加了苹果手机,这时候我们的代码该怎么修改

首先,我们肯定是要增加苹果手机类IPhone,并且实现Phone基类

京东类中订购方法的逻辑需要做出相应的修改

淘宝类中订购方法的逻辑也需要做出相应的修改,修改的地方和京东类一模一样。这时我们就发现同样的代码需要修改两次。

如果订购类有很多,除了京东、淘宝,还有拼多多、微信商城等等。那就意味着同样的代码不止要修改两次,有多少个订购类就需要修改多少次

这个工作量是很大的,而且极其容易出错,就问你头秃不头秃

这时候就需要使用简单工厂模式来优化我们的代码

简单工厂模式就是创建一个工厂类,由这个类来封装实例化对象的行为

套用到这个例子中就是:创建一个工厂类,由工厂类来封装创建手机的逻辑。订购类从工厂类中获取手机对象直接使用,不再关心手机创建的过程

工厂类PhoneFactory用代码实现就是这样

public class PhoneFactory {public static Phone createPhone(String type) {Phone phone = null;if ("huawei".equals(type)) {phone = new Huawei();} else if ("xiaomi".equals(type)) {phone = new Xiaomi();} else if ("apple".equals(type)) {phone = new IPhone();} else {System.out.println("暂不支持");}return phone;}
}

京东、淘宝等订购类从工厂类里面获取手机对象后直接使用,不再关心手机的创建过程(京东和淘宝类的代码一样,这里只贴京东类的代码)

public class Jingdong {public void order(String type) {Phone phone = PhoneFactory.createPhone(type);if (phone != null) {phone.play();}}
}

这就实现了简单工厂模式,以后再需要增加手机型号时只需要修改工厂类就行了,其他代码不用修改

简单工厂模式总结

简单工厂模式就是创建一个工厂类,根据传入的参数类型来创建具体的产品对象,并返回产品对象的实例

主要适用于调用者不知道应该创建哪个具体的对象,只能根据传入的条件返回相应对象的场景

比如案例中,订购类是不知道要创建哪个手机对象的,只能根据用户提供的条件才能知道需要哪个手机对象

简单工厂模式的好处在于将对象的创建过程和使用过程进行解耦,减少新增具体产品时修改代码的复杂度

就像上面的例子一样,对象的创建过程由工厂类负责,订购类不需要关心对象是怎么创建的,只需要从工厂类获取对象来使用即可

当需要增加手机对象时,只需要修改工厂类,而不需要对每一个订购类进行修改

简单工厂模式的缺点在于每次新增具体产品时,都需要修改工厂类,这违背了设计模式中的开闭原则。而且当具体的产品比较多时,工厂类的if-else判断就会比较多,代码不美观

工厂方法模式

实际案例

基于刚才用户订购手机玩游戏的需求,我们稍微改动一下。

为了实现精准营销,京东、淘宝等商城分别上线了华为专卖店、小米专卖店和苹果专卖店

当用户进入华为专卖店,就默认用户要订购华为手机;当用户进入小米专卖店,就默认用户要订购小米手机;当用户进入苹果专卖店,就默认用户要订购苹果手机

这个需求用刚才我们讲的简单工厂模式也可以实现

但是简单工厂的缺点也很明显,当新增粉丝类型时需要修改工厂类,当粉丝类型过多时工厂类的逻辑就会比较繁杂

比如新增了vivo粉丝,工厂类就需要新增判断条件去创建vivo手机对象;新增了oppo手机,工厂类就要新增判断条件去创建oppo手机对象。一直不断的新增下去的话,就会导致工厂类的中的判断过多,代码很长,后期不容易维护

而且,简单工厂模式是适用于调用者不知道应该创建哪种对象的场景。

在这个需求中,京东等订购类中为不同的粉丝提供了专卖店,假如专卖店是订购类中的一个方法的话,在专卖店这个方法中是知道应该创建什么样的对象的。比如,在华为手机的订购方法中,是知道要创建华为手机对象的

所以,这个需求可以用工厂方法模式来实现

工厂方法模式和简单工厂模式相似,也需要有一个工厂类。不过在工厂方法模式中,工厂类不再负责创建对象。因为在每个订购方法中已经知道应该创建哪个手机对象,所以创建对象的逻辑下沉到订购类的方法中

工厂类只负责制定规范,来约束每个产品的具体行为,所以工厂类是一个接口基类。每个对应的产品需要有一个自己的工厂,来继承这个基类,达到约束自身行为的目的

这个需求中工厂基类规定每个工厂只能有一个方法,这个方法的作用就是创建手机对象

工厂基类PhoneFactory用代码实现

public interface PhoneFactory {Phone createPhone();
}

华为工厂类用代码实现

public class HuaweiFactory implements PhoneFactory {@Overridepublic Phone createPhone() {return new Huawei();}
}

小米工厂类用代码实现

public class XiaomiFactory implements PhoneFactory {@Overridepublic Phone createPhone() {return new Xiaomi();}
}

在订购类中,不同的订购方法调用不同的工厂获取对象。比如京东订购类的代码如下(淘宝订购类处理逻辑类似,这里不再贴淘宝类的代码)

public class Jingdong {// 华为粉丝订购华为手机public void orderHuawei() {PhoneFactory phoneFactory = new HuaweiFactory();Phone phone = phoneFactory.createPhone();phone.play();}// 小米粉丝订购小米手机public void orderXiaomi() {PhoneFactory phoneFactory = new XiaomiFactory();Phone phone = phoneFactory.createPhone();phone.play();}
}

这样我们就用工厂方法模式实现了为不同粉丝订购不同手机的需求

工厂方法模式总结

工厂方法模式是定义一个工厂接口基类,基类中定义一个创建产品的抽象方法。每个产品需要有自己的工厂来实现这个基类,并完成创建对应产品实例的方法,由具体的产品调用该方法来创建对象

它主要适用于调用者已经明确知道需要创建哪一个具体产品的场景

比如,针对华为的粉丝,已经明确知道要创建华为的手机产品

工厂方法模式的优势在于完全符合了开闭原则,在新增产品时不需要再改动已存在的代码,使工厂类和产品类的代码完全解耦,更利于程序的扩展

他的缺点也很明显,当新增产品时,需要同时新增产品类和工厂类,导致系统中的类是成对增加,增加了系统的复杂度

抽象工厂模式

实际案例

基于工厂方法模式的案例,我们再进一步扩展

用户不单单想订购手机来玩游戏,还想订购ipad和电脑

可以用刚才讲的工厂方法模式来实现:我们不仅需要提供手机工厂的基类,还需要提供ipad工厂基类和电脑工厂基类,并且为每个工厂基类提供具体的工厂实现类

订购类方法中,根据不同的需求来创建不同的产品供用户使用

这样实现的代码没有问题,但是不符合我们真实开发中的业务场景

在实际业务场景中,京东商城的华为专卖店想要订购手机不需要到华为公司的手机部门去订购吧?想要订购ipad不需要到华为公司的ipad部门订购吧?想要订购电脑也不需要到华为公司的电脑部门订购吧?

京东商城的华为专卖店应该只负责和华为公司对接,和具体的业务部门没关系。专卖店想要订购某个产品去告诉华为公司,由公司去给具体的业务部门沟通

所以,从实际的使用场景出发,我们的代码应该这样设计

不再使用单独的手机工厂、ipad工厂和PC工厂,而是把同一个厂家作为工厂,由工厂分别创建不同的产品

Factory基类实现代码如下

public interface Factory {Phone createPhone();IPad createIPad();PC createPC();
}

华为工厂类实现代码如下

public class HuaweiFactory implements Factory {@Overridepublic Phone createPhone() {return new HuaweiPhone();}@Overridepublic IPad createIPad() {return new HuaweiIPad();}@Overridepublic PC createPC() {return new HuaweiPC();}
}

小米工厂实现代码如下

public class XiaomiFactory implements Factory {@Overridepublic Phone createPhone() {return new XiaomiPhone();}@Overridepublic IPad createIPad() {return new XiaomiIPad();}@Overridepublic PC createPC() {return new XiaomiPC();}
}

在京东订购类中,我们只需要创建对应的工厂对象,由工厂对象创建不同的产品

public class Jingdong {// 华为粉丝订购手机、ipad、电脑public void orderHuawei() {Factory factory = new HuaweiFactory();Phone phone = factory.createPhone();phone.play();IPad ipad = factory.createIPad();ipad.play();PC pc = factory.createPC();pc.play();}// 小米粉丝订购手机、ipad、电脑public void orderXiaomi() {Factory factory = new XiaomiFactory();Phone phone = factory.createPhone();phone.play();IPad ipad = factory.createIPad();ipad.play();PC pc = factory.createPC();pc.play();}
}

这样我们就用抽象工厂模式实现了用户订购手机、ipad和电脑的需求

抽象工厂模式总结

抽象工厂模式是将具有一定共性的产品封装到一块,由工厂类分别为这些产品提供创建对象的方法,调用者可以根据不同的需求调用工厂类的具体方法来获得产品实例

比如案例中华为的手机、ipad和电脑都属于华为公司产品,所以可以由华为工厂类来负责分别创建不同的对象

它的优势在于将具有一定共性的产品集合封装到一起,在实际开发中更符合具体的业务场景

他的缺点就是降低了系统的扩展性,当新增产品时需要修改工厂类,在工厂类的基类和实现类中都需要增加对应的方法

比如说,用户也想订购VR眼镜来玩游戏。那么工厂基类中需要增加创建VR眼镜的方法,所有的工厂实现类中都需要增加对该方法的实现,系统扩展性比较差

新同事说工厂模式有啥用,别学了相关推荐

  1. [Head First设计模式]饺子馆(冬至)中的设计模式——工厂模式

    系列文章 [Head First设计模式]山西面馆中的设计模式--装饰者模式 [Head First设计模式]山西面馆中的设计模式--观察者模式 [Head First设计模式]山西面馆中的设计模式- ...

  2. 【转载】.NET设计模式之抽象工厂模式(Abstract Factory)

    转载地址:http://www.cnblogs.com/Terrylee/archive/2005/12/13/295965.html 概述 在软件系统中,经常面临着"一系列相互依赖的对象& ...

  3. 工厂模式C++实现(三种工厂模式附详细注释)

    工厂模式(统称) 工厂模式是一种创建型模式,适用场景:安全的创建对象. 简单工厂模式 顾名思义,工厂是用来生产东西的,而在C++里面就是用来生产对象的. 就像一家餐厅一样,你可以按照你的方式来点餐.在 ...

  4. 将简单工厂模式改造应用到项目中,而不是纸上谈兵

    10月26日晚补充:经过掘友的提醒,我才发现之前我这篇所写的策略模式,其本身更偏向于工厂模式,我起初以为是掘友分不清工厂模式和策略模式,实际上是我自己把自己绕进去,看不清工厂模式和策略模式的区别. 因 ...

  5. Python工厂模式一

    工厂模式简介 在面向对象编程中,术语"工厂"表示一个负责创建其他类型对象的类.通常情况下,作为一个工厂的类有一个对象以及与它关联的多个方法.客户端使用某些参数调用此方法,之后,工厂 ...

  6. 【Java萌新】面试常问设计模式——工厂模式

    临近秋招,备战暑期实习,祝大家每天进步亿点点!Day17 本篇总结的是 工厂设计模式,后续会每日更新~ 1.工厂模式简介 ⼯⼚模式介绍:它提供了⼀种创建对象的最佳⽅式,在创建对象时 不会对客户端暴露创 ...

  7. 设计模式 之美 -- 简单工厂模式

    文章目录 1. 解决问题 2. 应用场景 3. 实现 C++实现: C语言实现 4. 缺点 1. 解决问题 举例如下: 我们实现一个卖衣服的功能,衣服的种类有很多:帽子,裤子,T恤... 每卖一种衣服 ...

  8. java 工厂模式的写法_设计模式-工厂模式

    一.概述 什么是工厂模式? 工厂模式(Factory Pattern)是最常见的一种设计模式之一.它主要是提供一种创建对象的最佳方法! 为什么要学习工厂模式? 与通过new来创建对象不同,使用工厂模式 ...

  9. 23种设计模式之单例模式、工厂模式、原型模式、建造者模式

    系列文章目录 第一章:程序设计原则-单一职责.接口隔离.依赖倒置.里式替换 第二章:程序设计原则-开闭原则.迪米特法则.合成复用原则 文章目录 系列文章目录 一.设计模式简单介绍 1.1.什么是设计模 ...

最新文章

  1. vi 从第几行到第几行 替换_第三十三章:查找新函数:XLOOKUP,再也不用趴着电脑屏幕数第几列、第几行(二)...
  2. linux deepin/ubuntu安装flameshot火焰截图
  3. 从软件工程看,语言只是工具
  4. Linux学习笔记:安装python
  5. 如何在Marketing Cloud Launchpad里打开外部链接
  6. java12章_从零开始学Java 第12章 异常处理
  7. 程序猿怎样的生活方式才能兼顾工作、家庭和自我提升
  8. Python的下载安装图文教程(超详细!!!)
  9. 171-路飞12-课程页面和课程数据表构建
  10. 如何将多个Excel 表合并成一个
  11. 通过分析双色球历史中奖数据-增加机选号码中奖概率
  12. 一个“蝇量级” C 语言协程库 -- Protothreads
  13. uni-app app端用highcharts绘制图表,并生成海报保存到手机相册
  14. Iperf测试能ping通,测试带宽失败
  15. 眼见为实:关于微服务熔断这几个知识点,你可能理解错了
  16. 选择题汇总4(括号里填的答案都是对的,不用管下面那个答案正确与错误,因为作者懒得删了)
  17. JAVA虚拟机--JVM
  18. 解决 openstack-nova-scheduler/conductor 开启失败
  19. 关于oracle账户被锁定的解决办法
  20. 未来dna计算机,DNA计算机领域重要进展:DNA模拟电路进行数学运算

热门文章

  1. android中menu菜单扩增_【已解决】Android添加Menu菜单
  2. python第三方库jieba下载_Python第三方库____jieba
  3. 定期存款单的mysql编写程序_MySQL 调优和使用必读
  4. 如何使用htmlq提取html文件内容
  5. JSP 异常处理如何处理?
  6. java if and_Java运算符-if分支语句
  7. python中使用socket编程实现带有界面的客户端向服务端发送文件和下载文件
  8. milp的matlab的案例代码_matlab30个案例分析案例6代码
  9. php memcache 封装类,PHP 自定义session储存 MEMCACHE 方式类
  10. SP5971 LCMSUM - LCM Sum(莫比乌斯反演 ,推柿子,经典)