博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
设计模式-工厂模式
阅读量:4163 次
发布时间:2019-05-26

本文共 7425 字,大约阅读时间需要 24 分钟。

文章目录

简单工厂模式

大家都很喜欢吃面条,面条有很多种类,有泡面、兰州拉面、莆田卤面等。

抽象出一个面条接口类(产品接口类):

public interface Noodles {
void desc();}

泡面实现类(具体产品实现类):

public class PaoNoodlesImpl implements Noodles{
@Override public void desc() {
System.out.println("简单工厂模式:程序员最爱吃的泡面"); }}

兰州拉面实现类(具体产品实现类):

public class LzNoodlesImpl implements Noodles {
@Override public void desc() {
System.out.println("简单工厂模式:兰州拉面,闻名遐迩"); }}

莆田卤面实现类(具体产品实现类):

public class PutianNoodlesImpl implements Noodles {
@Override public void desc() {
System.out.println("简单工厂模式:莆田卤面,我的最爱"); }}

定义一个简单工厂类:

public class SimpleNoodlesFactory {
public static final int TYPE_LZ = 1;//兰州拉面 public static final int TYPE_PM = 2;//泡面 public static final int TYPE_PT = 3;//莆田卤面 public static Noodles createNoodles(int type) {
switch (type) {
case TYPE_LZ: return new LzNoodlesImpl(); case TYPE_PM: return new PaoNoodlesImpl(); case TYPE_PT: default: return new PutianNoodlesImpl(); } }}

测试类:

@Controller@RequestMapping("/factory")public class FactoryTestController {
@RequestMapping("/simple.json") @ResponseBody public String simple() {
Noodles noodles = SimpleNoodlesFactory.createNoodles(SimpleNoodlesFactory.TYPE_PT); noodles.desc(); return "simple factory success"; }}

类图

在这里插入图片描述
特点

  • 这个工厂类是一个具体的类,非接口、抽象类。有一个重要的create()方法,利用if或者 switch创建产品并返回
  • 一个工厂负责创建所有实例
  • create()方法通常是静态的,所以也称之为静态工厂

缺点

  • 扩展性差(我想增加一种面条,除了新增一个面条产品类,还需要修改工厂类方法)
  • 不同的产品需要不同额外参数的时候,不支持

工厂方法模式

模式描述

为外部提供一个用于创建对象的接口(工厂接口),而不是具体的工厂类了,让其实现类(工厂实现类)决定实例化哪一个类(产品类),并且由该实现类创建对应类的实例

模式作用

可以一定程度上解耦,消费者和产品实现类隔离开,只依赖产品接口(抽象产品),产品实现类如何改动与消费者完全无关。

可以一定程度增加扩展性,若增加一个产品实现,只需要实现产品接口,修改工厂创建产品的方法,消费者可以无感知。

可以一定程度增加代码的封装性、可读性。清楚的代码结构,对于消费者来说很少的代码量就可以完成很多工作。

另外,抽象工厂才是实际意义的工厂模式,工厂方法只是抽象工厂的一个比较常见的情况

适用场景

消费者不关心它所要创建对象的类(产品类)的时候。

消费者知道它所要创建对象的类(产品类),但不关心如何创建的时候。

例如:hibernate里通过sessionFactory创建session等等。

模式要素

涉及如下四种角色

  • 抽象工厂角色:是工厂方法模式的核心,与应用程序无关,任何在该模式中创建的对象的工厂类必须实现这个接口(也可以是抽象类)
  • 具体工厂角色:实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建产品对象,允许有多个工厂实现类
  • 抽象产品角色:工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口
  • 具体产品角色:实现了抽象产品角色所定义的接口。某具体产品有专门的具体工厂创建,它们之间往往一一对应

图解说明

在这里插入图片描述
具体的工厂A和B是完全独立的,且各对应一个产品接口,与抽象工厂Abstract Factory是不同的(下面会介绍)

产品类图

在这里插入图片描述
工厂类图
在这里插入图片描述

代码实现

产品接口类:

public interface Message {
Map
getMessageParam(); void setMessageParam(Map
messageParam); /** * 发送通知 */ void sendMessage();}

产品抽象类:

public abstract class AbstractMessage implements Message {
/** * 生产产品所需要的原材料 */ private Map
messageParam; @Override public Map
getMessageParam() {
return this.messageParam; } @Override public void setMessageParam(Map
messageParam) {
this.messageParam = messageParam; }}

产品实现类(邮件):

public class EmailMessageImpl extends AbstractMessage{
@Override public void sendMessage() {
System.out.println("工厂方法模式:邮件发送,携带参数[" + getMessageParam().get("email") + "]"); }}

产品实现类(短信):

public class SmsMessageImpl extends AbstractMessage{
@Override public void sendMessage() {
System.out.println("工厂方法模式:短信发送,携带参数[" + getMessageParam().get("sms") + "]"); }}

工厂接口类:

public interface MessageFactory {
Message createMessage(String messageType);}

工厂实现类(这里只列出一个实现类,其实可以定义很多实现类):

public class MyMessageFactoryImpl implements MessageFactory {
@Override public Message createMessage(String messageType) {
// 这里的方式是:消费者知道自己想要什么产品 // 若生产何种产品完全由工厂决定,则这里不应该传入控制生产的参数 Map
messageParam = new HashMap
(); Message message = null; if ("EMAIL".equals(messageType)) {
messageParam.put("email", "email is 12345"); message = new EmailMessageImpl(); } else if ("SMS".equals(messageType)) {
messageParam.put("sms", "sms is 110"); message = new SmsMessageImpl(); } else {
messageParam.put("sms", "sms is 110"); message = new SmsMessageImpl(); } message.setMessageParam(messageParam); return message; }}

测试类:

@Controller@RequestMapping("/factory")public class FactoryTestController {
/** * 工厂方法模式 * @return */ @RequestMapping("/method.json") @ResponseBody public String method() {
MessageFactory messageFactory = new MyMessageFactoryImpl(); //邮件通知 Message message = messageFactory.createMessage("EMAIL"); message.sendMessage(); //短信通知 message = messageFactory.createMessage("SMS"); message.sendMessage(); return "method factory success"; }}

抽象工厂模式

定义

为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类

图解

在这里插入图片描述

抽象工厂模式和工厂方法模式区别

  • 抽象工厂模式是工厂方法模式的升级版本,他用来创建一组相关或者相互依赖的对象
  • 工厂方法模式针对的是一个产品等级结构;而抽象工厂模式则是针对的多个产品等级结构。在编程中,通常一个产品结构,表现为一个接口或者抽象类,也就是说,工厂方法模式提供的所有产品都是衍生自同一个接口或抽象类,而抽象工厂模式所提供的产品则是衍生自不同的接口或抽象类
  • 在抽象工厂模式中,有一个产品族的概念:所谓的产品族,是指位于不同产品等级结构中功能相关联的产品组成的家族。抽象工厂模式所提供的一系列产品就组成一个产品族;而工厂方法提供的一系列产品称为一个等级结构

举一个汽车的例子:

在这里插入图片描述

  • 在上面的类图中,两厢车和三厢车称为两个不同的等级结构
  • 2.0排量两厢车和2.4排量两厢车属于同一个等级结构,2.0排量三厢车和2.4排量三厢车属于另一个等级结构
  • 2.0排量两厢车和2.0排量三厢车属于同一个产品族,2.4排量两厢车和2.4排量三厢车属于另一个产品族

如果工厂的产品全部属于同一个等级结构,则属于工厂方法模式;如果工厂的产品来自多个等级结构,则属于抽象工厂模式。

在本例中,如果一个工厂模式提供2.0排量两厢车和2.4排量两厢车,那么他属于工厂方法模式;如果一个工厂模式是提供2.4排量两厢车和2.4排量三厢车两个产品,那么这个工厂模式就是抽象工厂模式,因为他提供的产品是分属两个不同的等级结构。

当然,如果一个工厂提供全部四种车型的产品,因为产品分属两个等级结构,他当然也属于抽象工厂模式了。

抽象工厂模式代码

/*** 抽象工厂类**/public abstract class AbstractFactory {
public abstract Flyable createFlyable(); public abstract Moveable createMoveable(); public abstract Writeable createWriteable(); } /*** 抽象工厂实现类**/public class Factory1 extends AbstractFactory {
@Override public Flyable createFlyable() {
return new Aircraft(); } @Override public Moveable createMoveable() {
return new Car(); } @Override public Writeable createWriteable() {
return new Pen(); } } /*** 抽象产品Flyable类**/public interface Flyable {
public void fly(int height); } /*** Flyable产品实现类**/public class Aircraft implements Flyable {
@Override public void fly(int height) {
System.out.println("我是一架客运机,我目前的飞行高度为:" + height + "千米。"); } } /*** 测试**/public class FactoryTest {
public static void main(String[] args) {
AbstractFactory factory = new Factory1(); Flyable flyable = factory.createFlyable(); flyable.fly(1589); Moveable moveable = factory.createMoveable(); moveable.run(87.6); Writeable writeable = factory.createWriteable(); writeable.write("Hello World."); } }

抽象工厂优点

抽象工厂模式除了具有工厂方法模式的优点外,最主要的优点就是可以在类的内部对产品族进行约束。所谓的产品族,一般或多或少的都存在一定的关联,抽象工厂模式就可以在类内部对产品族的关联关系进行定义和描述,而不必专门引入一个新的类来进行管理.

抽象工厂缺点

产品族的扩展将是一件十分费力的事情,假如产品族中需要增加一个新的产品,则几乎所有的工厂类都需要进行修改。所以使用抽象工厂模式时,对产品等级结构的划分是非常重要的

适用场景

当需要创建的对象是一系列相互关联或相互依赖的产品族时,便可以使用抽象工厂模式。

说的更明白一点,就是一个继承体系中,如果存在着多个等级结构(即存在着多个抽象类),并且分属各个等级结构中的实现类之间存在着一定的关联或者约束,就可以使用抽象工厂模式。

假如各个等级结构中的实现类之间不存在关联或约束,则使用多个独立的工厂来对产品进行创建,则更合适一点

总结

  • 无论是简单工厂模式,工厂方法模式,还是抽象工厂模式,他们都属于工厂模式,在形式和特点上也是极为相似的,他们的最终目的都是为了解耦。
  • 在使用时,我们不必去在意这个模式到底工厂方法模式还是抽象工厂模式,因为他们之间的演变常常是令人琢磨不透的。经常你会发现,明明使用的工厂方法模式,当新需求来临,稍加修改,加入了一个新方法后,由于类中的产品构成了不同等级结构中的产品族,它就变成抽象工厂模式了;而对于抽象工厂模式,当减少一个方法使的提供的产品不再构成产品族之后,它就演变成了工厂方法模式
  • 所以,在使用工厂模式时,只需要关心降低耦合度的目的是否达到了。

转载地址:http://dwpxi.baihongyu.com/

你可能感兴趣的文章
k8s web终端连接工具
查看>>
手绘VS码绘(一):静态图绘制(码绘使用P5.js)
查看>>
链睿和家乐福合作推出下一代零售业隐私保护技术
查看>>
艾默生纪念谷轮™在空调和制冷领域的百年创新成就
查看>>
JavaSE_day14 集合中的Map集合_键值映射关系
查看>>
异常 Java学习Day_15
查看>>
Mysql初始化的命令
查看>>
浅谈HTML
查看>>
css基础
查看>>
Servlet进阶和JSP基础
查看>>
servlet中的cookie和session
查看>>
过滤器及JSP九大隐式对象
查看>>
【Python】学习笔记——-7.0、面向对象编程
查看>>
【Python】学习笔记——-7.2、访问限制
查看>>
【Python】学习笔记——-7.3、继承和多态
查看>>
【Python】学习笔记——-7.5、实例属性和类属性
查看>>
git中文安装教程
查看>>
虚拟机 CentOS7/RedHat7/OracleLinux7 配置静态IP地址 Ping 物理机和互联网
查看>>
Jackson Tree Model Example
查看>>
常用js收集
查看>>