文章目录

  • 工厂模式的三种形态
    • 简单工厂模式
    • 工厂方法模式
    • 抽象工厂模式

Spring学习目录

上一篇:(五)Spring之Bean的作用域

下一篇:(七)Bean的实例化方式

工厂模式的三种形态

  • 第一种:简单工厂模式(Simple Factory):不属于23种设计模式之一。简单工厂模式又叫做:静态工厂方法模式。简单工厂模式是工厂方法模式的一种特殊实现。
  • 第二种:工厂方法模式(Factory Method):是23种设计模式之一。
  • 第三种:抽象工厂模式(Abstract Factory):是23种设计模式之一。

简单工厂模式

简单工厂模式是工厂方法模式的一种特殊实现,又被称为:静态工厂方法模式。

简单工厂模式中的角色:

  • 抽象产品角色
  • 具体产品角色
  • 工厂类角色

先看一个披萨项目需求:要便于维护的扩展,要便于维护

披萨种类很多(希腊披萨GreekPizz、奶酪披萨CheesePizz)
披萨的制作有prepare,bake,cut,box
完成披萨店的订购功能


抽象产品角色
Pizz类:

public abstract class Pizz {protected String name;//披萨名字public abstract void prepare();//准备原材料public void bake(){//烘烤System.out.println(name + " baking");}public void cut(){//切割System.out.println(name + " cutting");}public void box(){//打包System.out.println(name + " boxing");}public void setName(String name) {this.name = name;}}

具体产品角色
奶酪披萨CheesePizz:

/*** 具体产品角色*/
public class CheesePizz extends Pizz{@Overridepublic void prepare() {System.out.println("给奶酪披萨准备原材料");}
}

希腊披萨GreekPizz:

/*** 具体产品角色*/
public class GreekPizz extends Pizz{@Overridepublic void prepare() {System.out.println("给希腊披萨准备原材料");}
}

工厂类角色

/*** 工厂类角色*/
public class PizzFactory {/*** 静态方法,根据用户传type,返回对应的pizz对象* 简单工厂模式中有一个静态方法,所以也被称为:静态工厂模式* @param type* @return pizz*/public static Pizz createPizz(String type){Pizz pizz = null;System.out.println("使用简单工厂模式");if (type.equals("greek")){pizz = new GreekPizz();pizz.setName("希腊披萨");}else if (type.equals("cheese")){pizz = new CheesePizz();pizz.setName("奶酪披萨");}else {System.out.println("披萨种类不存在");}return pizz;}
}

测试程序:

public class Client {public static void main(String[] args) {Pizz pizz = PizzFactory.createPizz("greek");pizz.prepare();pizz.bake();pizz.cut();pizz.box();Pizz pizz1 = PizzFactory.createPizz("cheese");pizz1.prepare();pizz1.bake();pizz1.cut();pizz1.box();}
}


优缺点:

  • 优点:客户端程序不需要关心对象的创建细节,需要哪个对象时,只需要向工厂索要即可,初步实现了责任的分离。
    客户端只负责“消费”,工厂负责“生产”。生产和消费分离。

  • 缺点一:假设现在需要扩展一个新的产品,工厂类的代码是需要修改的,显然违背了OCP原则。

  • 缺点二:工厂类的责任比较重大,不能出现任何问题,因为这个工厂类负责所有产品的生产,称为全能类,或者有人把它叫做上帝类。
    这个工厂类一旦出问题,整个系统必然全部瘫痪。

工厂方法模式

工厂方法模式可以解决简单工厂模式当中的OCP问题。
怎么解决的?一个工厂对应生产一种产品。
这样工厂就不是全能类了,不是上帝类了。
另外,也可以符合OCP原则。

工厂方法模式中的角色:

  • 抽象产品角色
  • 具体产品角色
  • 抽象工厂角色
  • 具体工厂角色

客户在点披萨时,可以点不同口味的披萨,例如北京的奶酪披萨、伦敦的奶酪披萨等,这时候可以创建不同的简单工厂类,从当前来说也是可以的,但是考虑到项目的规模,以及软件的可维护性、可扩展性就不是特别好。
这时候就要选择工厂方法模式,定义一个创建对象的抽象方法,由子类决定要实例化的类,工厂方法模式将对象的实例化推迟到子类。

抽象产品角色
Pizz

public abstract class Pizz {protected String name;//披萨名字public abstract void prepare();//准备原材料public void bake(){//烘烤System.out.println(name + " baking");}public void cut(){//切割System.out.println(name + " cutting");}public void box(){//打包System.out.println(name + " boxing");}public void setName(String name) {this.name = name;}}

具体产品角色
希腊披萨GreekPizz

/*** 具体产品角色*/
public class GreekPizz extends Pizz {@Overridepublic void prepare() {setName("希腊披萨");System.out.println("给希腊披萨准备原材料");}
}

奶酪披萨CheesePizz

/*** 具体产品角色*/
public class CheesePizz extends Pizz {@Overridepublic void prepare() {setName("奶酪披萨");System.out.println("给奶酪披萨准备原材料");}
}

北京披萨BJPizz

public class BJPizz extends Pizz{@Overridepublic void prepare() {setName("北京披萨");System.out.println("给北京披萨准备原材料");}
}

抽象工厂角色

/*** 抽象工厂角色* 方法不再是静态了,是抽象方法*/
public abstract class PizzFactory {public abstract Pizz createPizz();
}

具体工厂角色
希腊披萨工厂GreekPizzFactory

public class GreekPizzFactory extends PizzFactory{@Overridepublic Pizz createPizz() {return new CheesePizz();}
}

奶酪披萨工厂CheesePizzFactory


public class CheesePizzFactory extends PizzFactory{@Overridepublic Pizz createPizz() {return new CheesePizz();}
}

北京披萨工厂BJPizzFactory

public class BJPizzFactory extends PizzFactory{@Overridepublic Pizz createPizz() {return new BJPizz();}
}

测试程序:

public class Client {public static void main(String[] args) {PizzFactory pizzFactory = new CheesePizzFactory();// 注意:这里可以采用 简单工厂模式 进行隐藏Pizz pizz = pizzFactory.createPizz();pizz.prepare();pizz.bake();pizz.cut();pizz.box();PizzFactory pizzFactory1 = new GreekPizzFactory();Pizz pizz1 = pizzFactory1.createPizz();pizz1.prepare();pizz1.bake();pizz1.cut();pizz1.box();PizzFactory pizzFactory2 = new BJPizzFactory();Pizz pizz2 = pizzFactory2.createPizz();pizz2.prepare();pizz2.bake();pizz2.cut();pizz2.box();}
}


优缺点:
工厂方法模式的优点:
当你扩展一个产品的时候,符合OCP原则,因为只需要添加两个类,一个类是具体产品类,一个类是具体工厂类。都是添加类,没有修改之前的代码,所以符合OCP。

  • 一个调用者想创建一个对象,只要知道其名称就可以了。
  • 扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。
  • 屏蔽产品的具体实现,调用者只关心产品的接口。

工厂方法模式的缺点:
每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。

抽象工厂模式

抽象工厂模式相对于工厂方法模式来说,就是工厂方法模式是针对一个产品系列的,而抽象工厂模式是针对多个产品系列的,即工厂方法模式是一个产品系列一个工厂类,而抽象工厂模式是多个产品系列一个工厂类。

抽象工厂模式特点:抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态。抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象。它有多个抽象产品类,每个抽象产品类可以派生出多个具体产品类,一个抽象工厂类,可以派生出多个具体工厂类,每个具体工厂类可以创建多个具体产品类的实例。
每一个模式都是针对一定问题的解决方案,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式针对的是多个产品等级结果。

抽象工厂中包含4个角色:

  • 抽象产品角色
  • 具体产品角色
  • 抽象工厂角色
  • 具体工厂角色

定义一个接口用于创建相关或有依赖关系的对象族,而无需指明具体的类。抽象工厂模式是简单工厂模式和工厂方法模式的整合和改进。

抽象产品角色
Pizz:

public abstract class Pizz {protected String name;//披萨名字public abstract void prepare();//准备原材料public void bake(){//烘烤System.out.println(name + " baking");}public void cut(){//切割System.out.println(name + " cutting");}public void box(){//打包System.out.println(name + " boxing");}public void setName(String name) {this.name = name;}}

具体产品角色
伦敦披萨家族:
伦敦胡椒披萨LDPepperPizz

/*** 具体产品角色* 伦敦胡椒披萨*/
public class LDPepperPizz extends Pizz{@Overridepublic void prepare() {setName("伦敦的胡椒披萨");System.out.println("伦敦胡椒披萨准备材料");}
}

伦敦奶酪披萨LDCheesePizz

/*** 具体产品角色* 伦敦奶酪披萨*/
public class LDCheesePizz extends Pizz{@Overridepublic void prepare() {setName("伦敦的奶酪披萨");System.out.println("伦敦奶酪披萨准备材料");}
}

北京披萨家族:
北京胡椒披萨BJPepperPizz

/*** 具体产品角色* 北京胡椒披萨*/
public class BJPepperPizz extends Pizz{@Overridepublic void prepare() {setName("北京的胡椒披萨");System.out.println("北京胡椒披萨准备材料");}
}

北京奶酪披萨BJCheesePizz

/*** 具体产品角色* 北京奶酪披萨*/
public class BJCheesePizz extends Pizz{@Overridepublic void prepare() {setName("北京的奶酪披萨");System.out.println("北京奶酪披萨准备材料");}
}

抽象工厂角色:

/*** 抽象工厂角色* 抽象工厂接口* 这个地方也可以是抽象类*/
public interface AbsFactory {//让下面的工厂子类具体实现Pizz createPizz(String ordertype);
}

具体工厂角色
伦敦工厂LDFactory

public class LDFactory implements AbsFactory{@Overridepublic Pizz createPizz(String ordertype) {Pizz pizz = null;if ("cheese".equals(ordertype)){pizz = new LDCheesePizz();}else if ("pepper".equals(ordertype)){pizz = new LDPepperPizz();}else{System.out.println("没有这个披萨");}return pizz;}
}

北京工厂BJFactory

public class BJFactory implements AbsFactory{@Overridepublic Pizz createPizz(String ordertype) {Pizz pizz = null;if ("cheese".equals(ordertype)){pizz = new BJCheesePizz();}else if ("pepper".equals(ordertype)){pizz = new BJPepperPizz();}else{System.out.println("没有这个披萨");}return pizz;}
}

测试程序:

public class Client {public static void main(String[] args) {AbsFactory factory = new BJFactory();Pizz BJcheese = factory.createPizz("cheese");Pizz BJpepper = factory.createPizz("pepper");BJcheese.prepare();BJcheese.bake();BJcheese.cut();BJcheese.box();BJpepper.prepare();BJpepper.bake();BJpepper.cut();BJpepper.box();AbsFactory factory2 = new LDFactory();Pizz LDcheese = factory2.createPizz("cheese");Pizz LDpepper = factory2.createPizz("pepper");LDcheese.prepare();LDcheese.bake();LDcheese.cut();LDcheese.box();LDpepper.prepare();LDpepper.bake();LDpepper.cut();LDpepper.box();}
}


优缺点:

  • 优点:当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
  • 缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在AbsFactory里加代码,又要在具体的里面加代码。

(六)Spring之回顾工厂模式相关推荐

  1. 解析Spring IOC原理——工厂模式与反射机制的综合应用

    (一)工厂模式 从一个例子开始讲起: 首先我们建立一个Chinese.java类,该类的sayHelloWorld(String name)方法,用中文对名为name的人问好,其内容如下: [java ...

  2. Spring框架之工厂模式

    简单的工厂模式 工厂模式:把原来分布在各个地方的对象的创建过程单独抽离出来,统一交给工厂类来创建所需的对象. (需要使用对象的时候,不要自己去new,通过工厂(方法)来创建对应的对象) 1.常规模式创 ...

  3. 浅谈Spring框架应用的设计模式(一)——工厂模式

    文章目录 前言 一.工厂模式介绍 1.简单工厂模式 (1)静态工厂模式 (2)利用反射机制实现的简单工厂 2.工厂方法模式 3.抽象工厂模式 二.Spring框架中工厂模式的重要应用 1.BeanFa ...

  4. 设计模式回顾——模板模式(C++)

    文章目录 1 前言 2 什么是模板模式 2.1 模板模式组成 2.2 模板模式UML图 2.3 模板模式作用 3 模板模式优缺点 4 什么地方使用模板模式 5 模板模式实现 6 模板模式与策略模式比较 ...

  5. 设计模式回顾——原型模式(C++)

    文章目录 1 前言 2 什么是原型模式 2.1 原型模式组成 2.2 原型模式UML图 2.3 原型模式作用 3 原型模式优缺点 4 什么地方使用原型模式 5 原型模式实现 6 原型模式与构造函数 1 ...

  6. 如何使用 Spring 实现策略模式+工厂模式

    欢迎关注方志朋的博客,回复"666"获面试宝典 一.策略模式 策略模式定义了一组算法,将每个算法都封装起来,并且使它们之间可以互换 1.策略模式主要角色 主要角色如下: 封装角色( ...

  7. 实践:使用Spring 原生注解来快速实现 策略模式 + 工厂模式

    作者:Richard_Yi juejin.im/post/5db0e910518825648f2ef355 前言 这阵子在做项目组重构的工作,工作中的一部分就是就目前代码库中与企业交互的逻辑抽离出来, ...

  8. java 反射 工厂_JAVA反射机制、工厂模式与SPRING IOC

    ABSTRACT Spring的IOC(控制反转)是Spring框架的灵魂,有了它才有了Spring的很多其他的灵活的特性.使用 Spring 开发项目时,控制层.业务层.DAO 层都是通过 IoC ...

  9. springboot工厂模式_最新整理138道阿里、快手等大厂面试题解析:基础+Spring+并发+JVM+设计模式+缓存...

    这些题目都是阿里.百度.美团.快手等一线互联网公司面试被问到的题目.熟悉本文中列出的知识点会大大增加通过前两轮技术面试的几率,希望可以帮助大家,祝大家求职顺利! Java集合22题 ArrayList ...

最新文章

  1. Redis的数据结构及应用场景
  2. python3 中的编码问题 unicode, utf-8, gbk, ascii
  3. ide 波浪线_零基础学习Python_小波浪
  4. 科大星云诗社动态20210320
  5. getpeername函数与getsockname函数的介绍
  6. 算法练习day16——190404(KMP算法)
  7. pay-as-you-go
  8. CodeForces - 501C Misha and Forest(拓扑排序)
  9. JAVA程序设计----面向对象(上)
  10. Graphics在java的哪个包_如何在Java中成功扩展Graphics
  11. vue使用element ui实现下拉列表分页的功能!!!
  12. 用英语描述计算机操作,操作系统的英文介绍
  13. Flutter Curves 动画曲线合辑
  14. PL/SQL Developer Initialization erro
  15. linux系统rootkit恶意软件安全检测工具rkhunter安装部署、使用详解
  16. Transformer入门Transformer和CNN之间的区别
  17. mysql8.0.15免安装版配置_Win10配置MySQL8.0.15免安装版教程
  18. 有必要买吗_婴儿床有必要买吗 婴儿床有用吗
  19. html里获得农历时间,获取阴历(农历)和当前日期的js代码_javascript技巧
  20. 2021年安全员-A证(江西省)报名考试及安全员-A证(江西省)考试平台

热门文章

  1. Linux 动态库的编译和使用
  2. vuex存储什么数据_【存储知识小讲堂系列】为什么数据隔离很重要
  3. 未来蓝牙新方向之一【AoA室内定位】
  4. 秀一下大连TimesTen 18.1培训的结业证
  5. 使用U8G2在oled屏幕上显示胡桃摇动画
  6. while和do...while循环测试总结
  7. 收集了一些distinct性能相关的文章 希望有用
  8. 【git tag使用】
  9. Appium日记20161031 徐慧迅
  10. 机器学习中ground truth的含义