前言

上一篇,我们介绍了简单工厂模式,它适用于产品数量较少且固定的情况,如果产品数量多或不固定,那么该模式会存在扩展性的问题。
所以,接下来我们介绍另一个具有扩展性且符合开闭原则的工厂模式–工厂方法模式。

开源车型创建框架

假设,我们把下面的代码开源到github上,作为智能配送程序的实现框架。


//请叫我“车型创建框架”,我可以避免你重复造轮子
public class CarFactory {//多态地创建产品public static Car create(Package package){Car car ;if(package.getWeight()<=10){car = new Bike();}else if (package.getWeight()<20){car = new Tricycle();}else{System.out.println("敬请期待!");}//所有的车子必须初始化,才能使用car.init();return car;}
}

开源后不久,我们收到了两条反馈信息:

1、我们除了有Bike和Tricycle外,还有载重30GK的卡车,但你的框架无法扩展我们自己的产品;

2、我们需要自行控制产品的创建条件(我们车子载重不允许超过标准的80%),但框架中把创建条件写死了。

抽象创建行为

第一个问题:无法扩展自定义的产品,我们只需要去掉static关键字,让CarFactory可继承,同时对外提供一个扩展点doCreate。如下:

//通过继承CarFactory实现自定义产品的扩展
public abstract class CarFactory {//去掉static关键字,让改方法可以被继承public  Car create(Package package){Car car ;if(package.getWeight()<=10){car = new Bike();}else if (package.getWeight()<20){car = new Tricycle();}else{//如果是框架之外的产品,调用子类的方法car=doCreate(package);}//所有的车子必须初始化,才能使用car.init();return car;}//对外提供扩展点,用于创建框架之外的产品public abstract Car doCreate(Package package);}

工厂方法模式

如果只是解决第一个问题,那么这样重构就可以了。但要解决第二个问题:“创建产品的条件写死了”,那我们需要去掉创建产品的条件和行为,让使用者能根据自身的实际情况创建产品。

//我绝对符合开闭原则:扩展开发,修改关闭
public abstract class CarFactory {//声明为final,关闭子类对该方法的修改public final Car create(){//去掉“个性化”的部分后,剩下的代码都是稳定不变的Car car =doCreate();car.init();return car;}//我是对创建行为的抽象,用于创建框架之外的产品public abstract Car doCreate();}

去掉创建产品的条件和行为后,如果直接把Bike和Tricycle暴露出去了,这就违背了我们使用工厂创建产品的初衷:隔离产品变化对客户类的影响。
既然CarFactory能支持自定义产品的扩展,当然也能支持框架提供的产品的扩展。所以,我们可以为每一个产品提供一个工厂,来隔离变化对客户类的影响。


//我的目的是隔离变化对客户类的影响
public class BikeFactory extends CarFactory{public Car doCreate(){return new Bike();}}//我承诺自己的类名、构造函数不发生变化
public class TricycleFactory extends CarFactory{public Car doCreate(){return new Tricycle();}}

扩展自定义产品

现在,我们模拟一下框架使用者如何扩展自定义产品以及控制产品创建逻辑。


//自定义产品
class Truck implements Car{}//通过继承抽象工厂扩展自定义产品
class TruckFactory extends CarFactory{}//机器人
public class Robot {public static void deliver(Package package){CarFactory carFactory ;//自行控制创建产品的条件if(package.getWeight()<=(10*0.8)){//创建框架提供的Bike工厂carFactory = new BikeFactory();}else if (package.getWeight()<(10*0.8)){//创建框架提供的Tricycle工厂carFactory = new TricycleFactory();}else if(package.getWeight()<(40*0.8)){//创建自定义的工厂carFactory = new TruckFactory();}else{System.out.println("敬请期待!");}//使用具体工厂创建具体产品Car car = carFactory.create();//装货car.load(package);//开车car.start();//停车car.stop();//卸货car.unload();}
}

可以看出,客户类Robot虽然不依赖具体的产品,但还是依赖了具体的工厂BikeFactory和TruckFactory。
这样,是不是又回到了起点(依赖具体对象)了呢?答案是肯定的,但具体工厂会比具体产品更具稳定,所以哪怕是依赖具体产品,只要是稳定不变的那么也是可行的。

教你用工厂方法模式重构代码相关推荐

  1. java设计模式7,一看就懂,架构灵魂,工厂方法模式

    目录 一.工厂模式 二.工厂方法模式的优缺点 1.优点 2.缺点 三.模拟场景 四.违背原则方案 1.思路清晰,简单明了 2.但是,似乎违反了一些设计原则: 五.通过工厂方法模式重构代码 1.定义购买 ...

  2. 你应该了解的工厂方法模式:优雅的代码永不过时

    文章目录 前言 一.举例说明工厂方法模式 1.程序分析 2.程序类图 3.程序代码 4.运行结果 二.工厂方法模式的定义 1.工厂方法模式的通用类图 2.工厂方法模式通用代码 三.工厂方法模式的应用 ...

  3. 设计模式学习-工厂方法模式

    在上文(设计模式学习-简单工厂模式)的模拟场景中,我们用简单工厂模式实现了VISA和MASTERARD卡的刷卡处理,系统成功上线并运行良好,突然有一天老大跑来说,我们的系统需要升级,提供对一般银联卡的 ...

  4. 设计模式:给你生产一个女朋友---工厂方法模式

    工厂方法模式 工厂方法模式是我们开发中使用最广泛的设计模式之一,不说无聊的定义,直接看例子 一.工厂方法模式的四大模块: 1.抽象工厂 --- 一个抽象类,有一个生产产品(女朋友)的抽象方法,由具体工 ...

  5. C#设计模式--工厂方法模式

    0.C#设计模式-简单工厂模式 设计模式: 工厂方法模式(Factory Method Pattern) 介绍:简单工厂模式是要在工厂类中通过数据来做个决策,在工厂类中的多个类中实例化出来其中一个要用 ...

  6. 设计模式----创建型设计模式(单例模式、工厂方法模式、构建者模式)

    创建型设计模式 单例模式(Singleton Pattern) 单例模式介绍 代码演示 饿汉式(静态常量) 饿汉式(静态代码块) 懒汉式(线程不安全) 懒汉式(线程安全,同步方法) 懒汉式(线程安全, ...

  7. 设计模式系列之 工厂方法模式

    定义 定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类.工厂方法让类的实例化推迟到子类中进行. 该定义是对生产者一方的描述,涉及四种角色,包括接口.接口实现类.被实例化的类.抽象产品(隐 ...

  8. 谜一般的设计模式:工厂方法模式和抽象工厂模式

    工厂方法模式 简单描述:也是创建型模式的一种,目的就是对象的创建和使用解耦.不需要关心对象的创建过程,说白了张嘴要就行. 应用场景:网上那些冠冕堂皇的应用场景,真的懒得粘了,啥时候补充一个具体的项目应 ...

  9. 快速理解工厂方法模式,及其在源码中的应用

    (一).什么是工厂方法模式 有一个总工厂负责生产各种电视产品,此时来了一个生产小米电视的需求,就会分配出一个制作小米电视的工厂,然后就能用该工厂生产小米电视了. 上面这种通过工厂来实例化类的方式抽象到 ...

最新文章

  1. oracle+restore+pfile,RAC(11gR2) OCR BACKUP RESTORE
  2. ubuntu mysql 中午_Ubuntu更改MySQL字符集UTF-8,正确显示中文
  3. 操作class属性的新API--classList
  4. ie6和W3C的盒子模型
  5. 保护MySQL数据仓库的5个小技巧
  6. 最新的中国风歌曲——《颜如玉》
  7. 蓝牙技术|传统手表品牌加入智能手表竞争,智能手表市场持续火热
  8. pycharm ssh interpreter 搭建
  9. unity3d 批量替换模型材质的脚本 一键替换模型及子物体材质
  10. Matlab之保存/写矩阵数据到文本(fprintf, save, dlmwrite)
  11. Grafana接入Elasticsearch数据,绘制dashboard
  12. JAVA性能优化,让程序更快更稳定
  13. Python中一些与word模板文件操作相关的库
  14. 【LaTex】 - 对齐符号的用法,换行符\\的用法,Misplaced 错误怎么解决
  15. 开源数据库MySQL DBA运维实战 第2章 SQL1
  16. Acrel-2000Z电力监控系统在某区块页岩气地面集输工程中的应用分析
  17. 在 Ubuntu 上安装 Sublime,亲测Ubuntu 18.04.6可用
  18. Inventor之入门
  19. 帷幄SDP - 智慧门店解决方案服务商 智慧零售解决方案公司
  20. 遇到问题: 文字输入后面的字就删除了

热门文章

  1. 2024内蒙古民族大学100210外科学724西医综合生理学考研强化5套卷
  2. Gitlab CI/CD 中预设变量 .gitlab-ci.yml 的预定义变量
  3. 二级计算机需要考哪些,哪些人需要考计算机二级?
  4. CentOS7 Git客户端安装升级
  5. python fileinput_Python中fileinput模块
  6. StringUtils.isEmpty用法
  7. 计算机毕业设计Java网上作业提交与批改系统(源码+系统+mysql数据库+Lw文档)
  8. 日语python怎么说_python – 将输出翻译成日语
  9. 2021年中国滚珠轴承市场趋势报告、技术动态创新及2027年市场预测
  10. spring下载教程