【设计模式2022】第四章 工厂模式

文章目录

  • 【设计模式2022】第四章 工厂模式
  • 一、概述
  • 二、简单工厂模式
    • 1.结构
    • 2.实现
    • 3.分析
    • 4.扩展
  • 三、工厂方法模式
    • 1.结构
    • 2.实现
    • 3.分析
  • 四、抽象工厂模式
    • 1.结构
    • 2.实现
    • 3.分析
  • 五、简单工厂+配置文件解除耦合
  • 六、Collection.iterator 方法

一、概述

设计一个咖啡类,并定义其两个子类(美式咖啡、拿铁咖啡),再设计一个咖啡店类

Coffee 抽象类:

public abstract class Coffee {public abstract String getName();public void addSugar(){System.out.println("加糖");}public void addMilk(){System.out.println("加奶");}
}

AmericanCoffee:

public class AmericanCoffee extends Coffee{@Overridepublic String getName() {return "美式咖啡";}
}

LatteCoffee:

public class LatteCoffee extends Coffee{@Overridepublic String getName() {return "拿铁咖啡";}
}

CoffeeStore:

public class CoffeeStore {public Coffee orderCoffee(String type){Coffee coffee = null;if("american".equals(type)){coffee = new AmericanCoffee();}else if("latte".equals(type)){coffee = new LatteCoffee();}else{throw new RuntimeException("没有这种咖啡");}coffee.addSugar();coffee.addMilk();return coffee;}
}

Client 测试类:

public class Client {public static void main(String[] args) {CoffeeStore store = new CoffeeStore();Coffee coffee = store.orderCoffee("latte");System.out.println(coffee.getName());}
}

存在的问题:
如果我们要新添加一种咖啡,就需要修改 CoffeeStore 类中的判断逻辑,这样就违背了开闭原则

因此,我们可以使用工厂模式来解决这个问题。采用工厂模式后,我们只需要和工厂打交道即可,彻底和对象解耦,如果需要更换对象,直接在工厂里更换该对象即可,达到了与对象解耦的目的

二、简单工厂模式

简单工厂不是一种模式,反而比较像是一种编程习惯

1.结构

简单工厂包含如下角色:

  • 抽象产品:定义了产品的规范,描述了产品的主要特性和功能
  • 具体产品:实现或者继承抽象产品的子类
  • 具体工厂:提供了创建产品的方法,调用者通过该方法来获取产品

2.实现

现在使用简单工厂对上面的案例进行改进,类图如下:

工厂类:

public class SimpleCoffeeFactory {public Coffee createCoffee(String type){Coffee coffee = null;if("american".equals(type)){coffee = new AmericanCoffee();}else if("latte".equals(type)){coffee = new LatteCoffee();}else{throw new RuntimeException("没有这种咖啡");}return coffee;}
}

3.分析

工厂类处理创建对象的细节,解除了 CoffeeStore 和 Coffee 实现类之间的耦合,但是又产生了新的耦合:CoffeeStore 和 工厂类的耦合以及工厂类和 Coffee 实现类的耦合

如果以后需要再添加新品种的咖啡,我们肯定需要修改工厂类的代码,还是会违反开闭原则

优点:
封装了创建对象的过程,可以通过参数直接获取对象。把对象的创建和业务逻辑层分开,这样就避免了以后修改客户代码,如果要实现新产品,只需要修改工厂类即可

缺点:
增加新产品时还是需要修改工厂类的代码,违背了“开闭原则”

4.扩展

静态工厂
有一部分开发者会将工厂类中创建对象的功能定义为静态的,这就是静态工厂模式,它同样不属于 23 种设计模式,代码如下:

public class SimpleCoffeeFactory {public static Coffee createCoffee(String type) {Coffee coffee = null;if("americano".equals(type)) {coffee = new AmericanoCoffee();} else if("latte".equals(type)) {coffee = new LatteCoffee();}return coffe;}
}

三、工厂方法模式

工厂方法模式完全遵循开闭原则。定义一个用于创建对象的接口,让子类决定实例化哪个产品类对象。工厂方法使一个产品类的实例化延迟到其工厂的子类

1.结构

工厂方法模式的主要角色:

  • 抽象工厂:提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法来创建产品
  • 具体工厂:主要是实现抽象工厂中的抽象方法,完成具体产品的创建
  • 抽象产品:定义了产品的规范,描述了产品的主要特性和功能
  • 具体产品:实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应

2.实现

工厂方法模式类图如下:

咖啡抽象类和咖啡具体类和之前保持一致

抽象工厂接口:

public interface CoffeeFactory {//创建咖啡对象的方法Coffee createCoffee();
}

美式咖啡具体工厂类:

public class AmericanCoffeeFactory implements CoffeeFactory{@Overridepublic Coffee createCoffee() {return new AmericanCoffee();}
}

拿铁咖啡具体工厂类:

public class LatteCoffeeFactory implements CoffeeFactory{@Overridepublic Coffee createCoffee() {return new LatteCoffee();}
}

咖啡店类:

public class CoffeeStore {private CoffeeFactory factory;public void setFactory(CoffeeFactory factory){this.factory = factory;}public Coffee orderCoffee(String type){Coffee coffee = factory.createCoffee();coffee.addMilk();coffee.addSugar();return coffee;}
}

Client 测试类:

public class Client {public static void main(String[] args) {CoffeeStore store = new CoffeeStore();CoffeeFactory factory = new AmericanCoffeeFactory();store.setFactory(factory);Coffee coffee = store.orderCoffee();System.out.println(coffee.getName());}
}

3.分析

工厂方法模式是对简单工厂模式的进一步抽象,使用了多态性,保持了简单工厂的优点,克服了它的缺点

优点:

  • 用户只需要知道具体工厂的名称就可以得到所要的产品,无须知道产品的具体创建过程
  • 在增加新产品时无需对原代码进行任何修改,满足开闭原则

缺点:

  • 每增加一个产品就需要增加一个工厂类

四、抽象工厂模式

为访问类提供一个创建一组相关或相互依赖的对象的接口,且访问类无须指定产品的具体类就能得到同族的不同等级的产品

抽象工厂模式是工厂方法模式的升级版,工厂方法模式只能生产一个等级的产品,而抽象工厂模式则可以生产多个等级的产品

1.结构

抽象工厂的主要角色如下:

  • 抽象工厂:提供了创建产品的接口,它包含了多个创建产品的方法,可以创建多个不同等级的产品
  • 具体工厂:主要是实现抽象工厂的多个抽象方法,完成具体产品的创建
  • 抽象产品:定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品
  • 具体产品:实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间是多对一的关系

2.实现

现在咖啡店业务发生改变,不仅要生产咖啡,还需要生产甜点,如提拉米苏、抹茶慕斯等,要是按照工厂方法模式,需要定义提拉米苏类、抹茶慕斯类、提拉米苏工厂、抹茶慕斯工厂、甜点工厂类。拿铁咖啡、,美式咖啡是一个产品等级,提拉米苏、抹茶慕斯是一个产品等级,拿铁咖啡和提拉米苏是同一产品族(意大利风味),美式咖啡和抹茶慕斯是同一产品族(美式风味)。类图如下:

咖啡抽象类和咖啡具体类和之前保持一致

甜品抽象类:

public abstract class Dessert {public abstract void show();
}

提拉米苏类:

public class Tiramisu extends Dessert{@Overridepublic void show() {System.out.println("提拉米苏");}
}

抹茶慕斯类:

public class MatchaMousse extends Dessert{@Overridepublic void show() {System.out.println("抹茶慕斯");}
}

甜品抽象工厂接口:

public interface DessertFactory {//生产咖啡的功能Coffee createCoffee();//生产甜品的功能Dessert createDessert();
}

美式风味具体工厂:

public class AmericanDessertFactory implements DessertFactory{@Overridepublic Coffee createCoffee() {return new AmericanCoffee();}@Overridepublic Dessert createDessert() {return new MatchaMousse();}
}

意大利风味具体工厂:

public class ItalyDessertFactory implements DessertFactory{@Overridepublic Coffee createCoffee() {return new LatteCoffee();}@Overridepublic Dessert createDessert() {return new Tiramisu();}
}

Client 测试类;

public class Client {public static void main(String[] args) {//创建的是意大利风味甜品工厂对象ItalyDessertFactory factory = new ItalyDessertFactory();//获取拿铁咖啡和提拉米苏甜品Coffee coffee = factory.createCoffee();Dessert dessert = factory.createDessert();System.out.println(coffee.getName());dessert.show();}
}

3.分析

如果要加同一个产品族的话,只需要再加一个对应的工厂类即可,不需要修改其他的类

优点:
当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象

缺点:
当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改

使用场景:

  • 当需要创建的对象是一系列相互关联或相互依赖的产品族时
  • 系统中有多个产品族,但每次只使用其中的某一族产品
  • 系统中提供了产品的类库,且所有产品的接口相同,客户端不依赖产品实例的创建细节和内部结构

五、简单工厂+配置文件解除耦合

可以通过工厂模式+配置文件的方式解除工厂对象和产品对象的耦合。在工厂类中加载配置文件中的全类名,并创建对象进行存储,客户端如果需要对象,直接进行获取即可

第一步:定义配置文件 bean.properties

american=com.sisyphus.factory.configFactory.AmericanCoffee
latte=com.sisyphus.factory.configFactory.LatteCoffee

第二步:改进工厂类

public class CoffeeFactory {//加载配置文件,获取配置文件中配置的全类名,并创建该类的对象进行存储//1.定义容器对象存储咖啡对象private static HashMap<String, Coffee> map = new HashMap<String, Coffee>();//2.加载配置文件,只需要加载一次static{//2.1 创建 Properties 对象Properties p = new Properties();//2.2 调用 p 对象中的 load 方法进行配置及文件的加载InputStream is = CoffeeFactory.class.getClassLoader().getResourceAsStream("bean.properties");try {p.load(is);//遍历 properties 集合对象Set<Object> keys = p.keySet();for(Object key : keys){//根据键获取值(全类名)String className = p.getProperty((String) key);//获取字节码对象Class<?> clazz = Class.forName(className);Coffee obj = (Coffee)clazz.newInstance();map.put((String)key,obj);}} catch (Exception e) {e.printStackTrace();}}public static Coffee createCoffee(String name){return map.get(name);}
}

静态成员变量用来存储创建的对象(键存储的是名称,值存储的是对应的对象),而读取配置文件以及创建对象写在静态代码块中,目的就是只需要执行一次

这样也符合开闭原则,新增产品时只需要在配置文件中新增配置即可,这种方式也是开发中比较实用的方式

六、Collection.iterator 方法

示例:

public class Demo {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("令狐冲");list.add("风清扬");list.add("任我行");//获取迭代器对象Iterator<String> it = list.iterator();//使用迭代器遍历while(it.hasNext()) {String ele = it.next();System.out.println(ele);}}
}

单列集合获取迭代器的方法使用到了工厂方法模式,以下是类图:

Collection 接口是抽象工厂类,ArrayList 是具体的工厂类;Iterator 接口是抽象产品类,ArrayList 类中的 Iter 内部类是具体的产品类。在具体的工厂类中 iterator() 方法创建具体的商品类的对象

【设计模式2022】第四章 工厂模式相关推荐

  1. 【设计模式】第四章 工厂模式

    第四章 工厂模式 文章目录 第四章 工厂模式 一.介绍 二.简单工厂模式 三.工厂方法模式 四.抽象工厂模式 一.介绍 工厂模式(Factory Pattern),工厂就是创建产品的地方,根据创建的产 ...

  2. 设计模式:第四章 中介模式

    第四章 中介模式 1. 核心思想 2. UML类图 3. 代码框架 4. 模型说明 4.1 设计要点 4.2 优缺点 5. 应用场景 注1 1. 核心思想 由中介来承接房客与房东之间的交互过程,可以使 ...

  3. 尚硅谷设计模式学习(四)工厂模式

    从披萨店的案例引入工厂模式 披萨的种类很多(比如 GreekPizza.CheesePizza 等) 披萨制作完成后需要进行cut(切片工作),box(包装工作) 完成披萨店的功能 一.简单工厂模式 ...

  4. 设计模式(6)——抽象工厂模式(Abstract Factory Pattern,创建型)

    1.概述 使用设计模式可以提高代码的可复用性.可扩充性和可维护性.抽象工厂模式(Abstract Factory Pattern)属于创建型模式,为创建一组相关或者相互依赖的对象(产品族)提供一个抽象 ...

  5. 第 6 章 工厂模式

    第 6 章 工厂模式 1.简单工厂模式 简单工厂模式的实际需求 看一个披萨的项目:要便于披萨种类的扩展,要便于维护 披萨的种类很多(比如 GreekPizz.CheesePizz 等) 披萨的制作有 ...

  6. java设计模式中不属于创建型模式_23种设计模式第二篇:java工厂模式定义:工厂模式是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式...

    23种设计模式第二篇:java工厂模式 定义: 工厂模式是 Java 中最常用的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 工厂模式主要是为创建对象提供过渡接口, ...

  7. 设计模式C#描述之——简单工厂模式、抽象工厂模式、单例与多例模式

    设计模式C#描述之--简单工厂模式 前 言:设计模式是软件开发领域的精髓之一.学好设计模式是目前每一个开发人员的必修课.目前关于设计模式的书很多,其中比较好的有GOF那本的中译本,但并 不很适合初学者 ...

  8. 设计模式(1)--简单工厂模式、策略模式

    设计模式(1)--简单工厂模式.策略模式 1. 简单工厂模式 在阎宏博士的<JAVA与模式>一书中开头是这样描述简单工厂模式的:简单工厂模式是类的创建模式,又叫做静态工厂方法(Static ...

  9. 【Java设计模式】简单学抽象工厂模式——你好,微信还是支付宝

    目录 说明 实现方式 自问自答 其他链接 说明 五大创建型模式之一,其他还有单例模式.原型模式.建造者模式.工厂模式. 抽象工厂模式(Abstract Factory Pattern):定义了一个in ...

最新文章

  1. 个人学习Linux决心书
  2. SAE 的极致应用部署效率
  3. 经典html5网页,HTML5网页设计经典
  4. Docker安装influxDB
  5. java 二维数组动态添加,菜鸟求助: 二维数组如何实现动态接收?
  6. 第四十四篇 面向对象高阶
  7. NC单点登录设置默认界面
  8. 菁搜FTP搜索引擎 photo
  9. Web全栈工程师应该会什么?
  10. 【报告分享】2021年中国商业物联网行业研究报告-艾瑞咨询(附下载)
  11. RadarNet: Efficient Gesture Recognition Technique Utilizing a Miniaturized Radar Sensor
  12. 几何分布的期望和方差公式推导_机器学习常用的方差、协方差与皮尔逊值
  13. ipc$与默认共享及ipc$连接失败的原因
  14. 阿卜杜拉·法兹里和两个哥哥的故事(二)
  15. java通过struts实现web中的文件下载
  16. 你应该知道的 setTimeout 秘密
  17. HTML和CSS基础系列(一)
  18. 计算机用老毛桃u盘备份系统,如何使用老毛桃winpe系统进行Ghost备份
  19. matlab2018a安装(里面有matlab2018a_win64的下载路径以及详细步骤,自己亲自测试运行没有问题!)
  20. Android中Launcher实例

热门文章

  1. VM虚拟机 Ubuntu 打不开外接摄像头
  2. 微信小程序蓝牙扫描搜不到信号
  3. 鸿蒙os系统发布会录像,鸿蒙os6月2日直播回放地址入口 鸿蒙2.0发布会直播回放 华为鸿蒙发布会完整视频...
  4. 基于蒙特卡洛法的概率潮流 以IEEE33节点的电网为研究对象 建立了光伏和风电的概率出力模型 采用蒙特卡洛法进行随机抽样
  5. 哈里斯:调查发现亚马逊首席执行官杰夫·贝佐斯最能创新
  6. [附源码]计算机毕业设计企业人事管理系统Springboot程序
  7. 巧用Photoshop滤镜模拟水粉花卉效果(转)
  8. 手机安装Linux系统
  9. linux py2exe,如何在Ubuntu上使用py2exe(或pyinstaller)创建.exe
  10. leyou商城项目搭建(1)-电商行业及乐优商城介绍