工厂方法模式、抽象工程模式

  • 前言
    • 工厂方法模式、 抽象工程模式
  • 1. 简单工厂模式(不属于GOF的23种经典设计模式)
    • 1.1 结构
    • 1.2 实现
    • 缺点
  • 2. 工厂方法模式
    • 2.1 结构
    • 2.2 实现
    • 优点、缺点
  • 3. 抽象工厂模式
    • 3.1 概念
    • 3.2 结构
    • 3.3 实现
    • 3.4 优点、缺点
  • 4. 简单工厂 + 配置文件解除耦合
    • 4.1 定义配置文件
    • 4.2 改进工厂类
  • 5. Collection.iterator方法
  • 6. 工厂方法和抽象工厂区别

前言

创建型模式的主要关注点是“怎样创建对象?”,它的主要特点是“将对象的创建与使用分离”。这样可以降低系统的耦合度,使用者不需要关注对象的创建细节。

创建型模式分为:
单例模式
工厂方法模式
抽象工程模式
原型模式
建造者模式

工厂方法模式、 抽象工程模式


工厂模式是用来创建对象的一种最常用的设计模式,不暴露创建对象的具体逻辑,而是将将逻辑封装在一个函数中,那么这个函数就可以被视为一个工厂。
其就像工厂一样重复的产生类似的产品,工厂模式只需要我们传入正确的参数,就能生产类似的产品

举个例子:
编程中,在一个 A 类中通过 new 的方式实例化了类 B,那么 A 类和 B 类之间就存在关联(耦合)
后期因为需要修改了 B 类的代码和使用方式,比如构造函数中传入参数,那么 A 类也要跟着修改,一个类的依赖可能影响不大,但若有多个类依赖了 B 类,那么这个工作量将会相当的大,容易出现修改错误,也会产生很多的重复代码,这无疑是件非常痛苦的事;
这种情况下,就需要将创建实例的工作从调用方(A类)中分离,与调用方「解耦」,也就是使用工厂方法创建实例的工作封装起来(「减少代码重复」),由工厂管理对象的创建逻辑,调用方不需要知道具体的创建过程,只管使用,「而降低调用者因为创建逻辑导致的错误」;

1. 简单工厂模式(不属于GOF的23种经典设计模式)

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

1.1 结构

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

1.2 实现


缺点

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

2. 工厂方法模式

2.1 结构

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

2.2 实现



优点、缺点

优点:用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程。
缺点:类的个数容易过多,增加复杂度
应用场景:客户只知道创建产品的工厂名,而不知道具体的产品名。

3. 抽象工厂模式

前面介绍的工厂方法模式中考虑的是一类产品的生产,如畜牧场只养动物、电视机厂只生产电视机、传智播客只培养计算机软件专业的学生等。
这些工厂只生产同种类产品,同种类产品称为同等级产品,也就是说:工厂方法模式只考虑生产同等级的产品,但是在现实生活中许多工厂是综合型的工厂,能生产多等级(种类) 的产品,如电器厂既生产电视机又生产洗衣机或空调,大学既有软件专业又有生物专业等。
本节要介绍的抽象工厂模式将考虑多等级产品的生产,将同一个具体工厂所生产的位于不同等级的一组产品称为一个产品族,下图所示横轴是产品等级,也就是同一类产品;纵轴是产品族,也就是同一品牌的产品,同一品牌的产品产自同一个工厂。

3.1 概念

是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。
抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品。

3.2 结构

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

3.3 实现

现咖啡店业务发生改变,不仅要生产咖啡还要生产甜点,如提拉米苏、抹茶慕斯等,要是按照工厂方法模式,需要定义提拉米苏类、抹茶慕斯类、提拉米苏工厂、抹茶慕斯工厂、甜点工厂类,很容易发生类爆炸情况。其中拿铁咖啡、美式咖啡是一个产品等级,都是咖啡;提拉米苏、抹茶慕斯也是一个产品等级;拿铁咖啡和提拉米苏是同一产品族(也就是都属于意大利风味),美式咖啡和抹茶慕斯是同一产品族(也就是都属于美式风味)。所以这个案例可以使用抽象工厂模式实现。类图如下:

抽象工厂:

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

具体工厂:

public class AmericanDessertFactory implements DessertFactory {public Coffee createCoffee() {return new AmericanCoffee();}public Dessert createDessert() {return new MatchaMousse();}
}
public class ItalyDessertFactory implements DessertFactory {public Coffee createCoffee() {return new LatteCoffee();}public Dessert createDessert() {return new Trimisu();}
}

抽象产品:

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

具体产品

public class AmericanCoffee extends Coffee {public String getName() {return "美式咖啡";}
}
public class LatteCoffee extends Coffee {public String getName() {return "拿铁咖啡";}
}
public class MatchaMousse extends Dessert {public void show() {System.out.println("抹茶慕斯");}
}
public class Trimisu extends Dessert {public void show() {System.out.println("提拉米苏");}
}

3.4 优点、缺点

如果要加同一个产品族的话,只需要再加一个对应的工厂类即可,不需要修改其他的类。
优点:
当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
缺点:
当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。

4. 简单工厂 + 配置文件解除耦合

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

4.1 定义配置文件

为了演示方便,我们使用properties文件作为配置文件,名称为bean.properties

american=com.itheima.pattern.factory.config_factory.AmericanCoffee
latte=com.itheima.pattern.factory.config_factory.LatteCoffee

4.2 改进工厂类

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

public class CoffeeFactory {private static Map<String,Coffee> map = new HashMap();static {Properties p = new Properties();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);}
}

5. Collection.iterator方法


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

  1. DateForamt类中的getInstance()方法使用的是工厂模式;
  2. Calendar类中的getInstance()方法使用的是工厂模式;

6. 工厂方法和抽象工厂区别

工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。
工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。

工厂方法模式: 一个抽象产品类,可以派生出多个具体产品类。 一个抽象工厂类,可以派生出多个具体工厂类。 每个具体工厂类只能创建一个具体产品类的实例。
抽象工厂模式: 多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。 一个抽象工厂类,可以派生出多个具体工厂类。 每个具体工厂类可以创建多个具体产品类的实例。

举个例子说明下:
用种蔬菜的例子来说明事实,最初的时候,由于规模小,只种植一种蔬菜,根菜类蔬菜,这个时候由于种植方式比较简单,采用简单工厂模式即可,主要目的是让工人轻松,下达工厂种植即可,但是随着种植厂的发展以及市场的需求,要增加一种蔬菜类型种植了,茎菜,由于茎菜与根菜种植方式不一致,就需要两个专门的种植工厂来进行管理,那么久采用工厂模式来管理,一个工厂负责一种作物的种植,这个时候产品可以理解为仍然在一个层次。但是随着科技的发展,我们逐步要种植转基因与非转基因食品了,在以前的蔬菜种类上又增加了一个层次,这个时候无法将其作为一个层次来解决,所以必须采用抽象工厂的方式来解决。我用UML图表示三种结构:



上面的UML图很明显的就看出来了,抽象工厂可以创建多个产品类对象,如在种菜工厂中,有种根菜,种茎菜。工厂模式与抽象工厂模式以及简单工厂模式只有在具体应用的时候,分析具体的产品层级,然后选择相应的设计模式。
而在每一个层次,种菜工人所关心的对象也不一样,在简单工厂模式下,工人要想到种植萝卜还是白菜,在工厂模式下,工人想到是种植根菜还是茎菜,而在抽象工厂模式下,则关心种植基因菜还是非基因菜

来源:https://www.bilibili.com/video/BV1Np4y1z7BU?p=43&spm_id_from=pageDriver&vd_source=b901ef0e9ed712b24882863596eab0ca
工厂方法和抽象工厂区别:https://blog.csdn.net/wyxhd2008/article/details/5597975
https://www.jianshu.com/p/6060e0632071

【设计模式】 - 创建者模式 - 工厂方法模式、抽象工程模式相关推荐

  1. 设计模式:工厂方法与抽象工厂模式

    说明:这篇blog写的很好,有助于理解工厂方法与抽象工厂模式的联系与区别. 原文链接:http://blog.csdn.net/yzxz/article/details/4601152 抽象工厂模式与 ...

  2. 2.5万字详解23种设计模式—创建型模式(简单工厂、工厂方法、抽象工厂、单例-多线程安全详解、建造者、原型)的详细解读、UML类图

    本文简述了各大设计模式,并通过UML和代码详细说明.本文大约共 2.5W 字,建议收藏.下方是本文的目录: 一.设计模式的认识 二.设计模式的分类 根据其目的 根据范围 三.设计模式的优点 四.设计模 ...

  3. 【设计模式】简单工厂模式+工厂方法模式+抽象工厂模式

    前提导论 故事 不采用工厂模式 简单工厂模式 工厂方法模式 故事 抽象工厂模式 故事结局 前提导论 为了学习设计模式时便于理解,我将用基于农夫和他的村子与森林为背景环境,讲一个故事时,阐述一个设计模式 ...

  4. 重学Java设计模式-创建者模式-工厂方法模式

    重学Java设计模式-创建者模式-工厂方法模式 内容摘自:重学 Java 设计模式:实战工厂方法模式「多种类型商品不同接口,统一发奖服务搭建场景」 | bugstack 虫洞栈 工厂方法模式介绍 图片 ...

  5. 设计模式学习笔记-2 创建者模式-工厂方法模式

    设计模式学习笔记-2 创建者模式-工厂方法模式 工厂模式介绍 工厂模式又称工厂方法模式,是一种创建型设计模式,其在父类中提供一个创建对象的方法,允许子类决定实例化对象的类型. 这种设计模式使Java开 ...

  6. 工厂方法模式、简单工厂模式、抽象工程模式

    1.概述 工厂设计模式是一种创建型模式,它提供了一种创建对象的最佳方式.在工厂模式中,我们创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象. 1.1. 针对的问题 在 ...

  7. 研磨23种大话设计模式------简单工厂模式 + 工厂方法模式 + 抽象工厂模式

    大家好,我是一位在java学习圈中不愿意透露姓名并苟且偷生的小学员,如果文章有错误之处,还望海涵,欢迎多多指正 如果你从本文 get 到有用的干货知识,请帮忙点个赞呗,据说点赞的都拿到了offer 简 ...

  8. 设计模式之工厂模式(工厂方法模式、抽象工厂模式)

    工厂模式 所谓工厂,就是将零件组装成产品的地方. 建一个对象常常需要复杂的过程,所以不适合包含在一个复合对象中.创建对象可能会导致大量的重复代码,可能会需要复合对象访问不到的信息,也可能提供不了足够级 ...

  9. 工厂模式 工厂方法模式 抽象工厂模式 简单工厂模式 工厂模式于抽象工厂的区别 设计模式

    工厂模式 定义一个用于创建对象的接口,让子类实现具体类的创建.工厂将类的实例化延迟的子类. 良好的分装性.对于具体产品,只要知道产品名称即可(类名或字符串),封闭了对产品创建的细节. 屏蔽具体产品类. ...

最新文章

  1. moment.js相关知识总结
  2. VS2019错误提示:_CRT_SECURE_NO_WARNINGS的解决方法
  3. 计算机视觉开源库OpenCV之边缘检测cv2.canny()函数
  4. 美创企推出仅90斤的物流无人车,成本低至5000美元
  5. 加速SaaS规模化演进,餐道基于K8s的云上创新底座
  6. 漫步最优化三十六——基本共轭方向法
  7. Hyper Text Transfer Protocol(超文本传输协议)
  8. 同期两篇 Nature:运行温度高于 1K 的量子计算平台问世!
  9. Device Mapper Multipath(DM-Multipath)
  10. 3.1~4 处理器架构IA32/x86介绍+IA32架构下汇编基本介绍
  11. 作为一名基层管理者如何利用情商管理自己和团队(一)
  12. lsb_slam Tracking线程 SE3Tracking 欧式变换矩阵跟踪参考帧 加权高斯牛顿优化算法WLM 最小二乘优化 归一化方差的光度误差函数 偏导数雅克比矩阵J 线性方程组LDLT求解
  13. python抢票_抢票工具成了GitHub热榜第一,最新支持候补抢票,Python跑起来 | 标星8400...
  14. 数字经济与数字化转型
  15. java安卓模拟器和电脑通信_PC电脑和Android模拟器访问及模拟器之间tcp/udp通信
  16. 【NO ST-LINK Detected】解决办法
  17. python中常见的三种选择结构_在Python中,实现多分支选择结构的最佳方法是
  18. Mac 命令行删除包含文件的文件夹
  19. HIT oslab之实验2 操作系统的引导(bootsect.s + setup.s)
  20. 当贝投影仪安装Youtube\Netflix\Spotify等应用

热门文章

  1. C语言字节对齐问题详解
  2. 杭电acm1004java答案_杭电acm1004源码
  3. 戴尔便携式计算机 故障,戴尔笔记常见故障有哪些?如何维修?
  4. Python如何不加载图片获取图片的分辨率(即尺寸,宽和高)?
  5. Go语言学习笔记【18】 Go语言常见库:html/template
  6. 【第98期】游戏策划:给@我有一个本子的应聘攻略
  7. laravel中上传图片并预览
  8. 教程:在Vivado中指定VSCode作为文本编辑器
  9. echarts饼图文字重叠问题及解决方法
  10. 印度“抵制微软活动”赞