【设计模式2022】第四章 工厂模式
【设计模式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】第四章 工厂模式相关推荐
- 【设计模式】第四章 工厂模式
第四章 工厂模式 文章目录 第四章 工厂模式 一.介绍 二.简单工厂模式 三.工厂方法模式 四.抽象工厂模式 一.介绍 工厂模式(Factory Pattern),工厂就是创建产品的地方,根据创建的产 ...
- 设计模式:第四章 中介模式
第四章 中介模式 1. 核心思想 2. UML类图 3. 代码框架 4. 模型说明 4.1 设计要点 4.2 优缺点 5. 应用场景 注1 1. 核心思想 由中介来承接房客与房东之间的交互过程,可以使 ...
- 尚硅谷设计模式学习(四)工厂模式
从披萨店的案例引入工厂模式 披萨的种类很多(比如 GreekPizza.CheesePizza 等) 披萨制作完成后需要进行cut(切片工作),box(包装工作) 完成披萨店的功能 一.简单工厂模式 ...
- 设计模式(6)——抽象工厂模式(Abstract Factory Pattern,创建型)
1.概述 使用设计模式可以提高代码的可复用性.可扩充性和可维护性.抽象工厂模式(Abstract Factory Pattern)属于创建型模式,为创建一组相关或者相互依赖的对象(产品族)提供一个抽象 ...
- 第 6 章 工厂模式
第 6 章 工厂模式 1.简单工厂模式 简单工厂模式的实际需求 看一个披萨的项目:要便于披萨种类的扩展,要便于维护 披萨的种类很多(比如 GreekPizz.CheesePizz 等) 披萨的制作有 ...
- java设计模式中不属于创建型模式_23种设计模式第二篇:java工厂模式定义:工厂模式是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式...
23种设计模式第二篇:java工厂模式 定义: 工厂模式是 Java 中最常用的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 工厂模式主要是为创建对象提供过渡接口, ...
- 设计模式C#描述之——简单工厂模式、抽象工厂模式、单例与多例模式
设计模式C#描述之--简单工厂模式 前 言:设计模式是软件开发领域的精髓之一.学好设计模式是目前每一个开发人员的必修课.目前关于设计模式的书很多,其中比较好的有GOF那本的中译本,但并 不很适合初学者 ...
- 设计模式(1)--简单工厂模式、策略模式
设计模式(1)--简单工厂模式.策略模式 1. 简单工厂模式 在阎宏博士的<JAVA与模式>一书中开头是这样描述简单工厂模式的:简单工厂模式是类的创建模式,又叫做静态工厂方法(Static ...
- 【Java设计模式】简单学抽象工厂模式——你好,微信还是支付宝
目录 说明 实现方式 自问自答 其他链接 说明 五大创建型模式之一,其他还有单例模式.原型模式.建造者模式.工厂模式. 抽象工厂模式(Abstract Factory Pattern):定义了一个in ...
最新文章
- 个人学习Linux决心书
- SAE 的极致应用部署效率
- 经典html5网页,HTML5网页设计经典
- Docker安装influxDB
- java 二维数组动态添加,菜鸟求助: 二维数组如何实现动态接收?
- 第四十四篇 面向对象高阶
- NC单点登录设置默认界面
- 菁搜FTP搜索引擎 photo
- Web全栈工程师应该会什么?
- 【报告分享】2021年中国商业物联网行业研究报告-艾瑞咨询(附下载)
- RadarNet: Efficient Gesture Recognition Technique Utilizing a Miniaturized Radar Sensor
- 几何分布的期望和方差公式推导_机器学习常用的方差、协方差与皮尔逊值
- ipc$与默认共享及ipc$连接失败的原因
- 阿卜杜拉·法兹里和两个哥哥的故事(二)
- java通过struts实现web中的文件下载
- 你应该知道的 setTimeout 秘密
- HTML和CSS基础系列(一)
- 计算机用老毛桃u盘备份系统,如何使用老毛桃winpe系统进行Ghost备份
- matlab2018a安装(里面有matlab2018a_win64的下载路径以及详细步骤,自己亲自测试运行没有问题!)
- Android中Launcher实例
热门文章
- VM虚拟机 Ubuntu 打不开外接摄像头
- 微信小程序蓝牙扫描搜不到信号
- 鸿蒙os系统发布会录像,鸿蒙os6月2日直播回放地址入口 鸿蒙2.0发布会直播回放 华为鸿蒙发布会完整视频...
- 基于蒙特卡洛法的概率潮流 以IEEE33节点的电网为研究对象 建立了光伏和风电的概率出力模型 采用蒙特卡洛法进行随机抽样
- 哈里斯:调查发现亚马逊首席执行官杰夫·贝佐斯最能创新
- [附源码]计算机毕业设计企业人事管理系统Springboot程序
- 巧用Photoshop滤镜模拟水粉花卉效果(转)
- 手机安装Linux系统
- linux py2exe,如何在Ubuntu上使用py2exe(或pyinstaller)创建.exe
- leyou商城项目搭建(1)-电商行业及乐优商城介绍