简单工厂模式缺陷

大白话简单工厂模式(Simple Factory Pattern)中通过买车的经历解释了简单工厂模式。但熟悉设计模式的朋友会发现一些问题。

  • 工厂类集中了所有实例(产品)的创建逻辑,一旦这个工厂不能正常工作,整个系统都会受到影响。用日产车工厂的例子来形容就是日产汽车的工厂负责所有车型的制造,当发生停电、火灾等情况时,汽车无法正常制造,大大影响汽车的销售,使企业陷入困境
  • 违背“开放 - 关闭原则”,一旦添加新产品就不得不修改工厂类的逻辑,这样就会造成工厂逻辑过于复杂。这句话的意思是当企业发布新产品,该工厂需要重新学习新车型的制造,加大工人压力。

所以,随着企业的发展,日产公司决定将每种车型进行分工厂制造,解决了上述问题。这种方法在设计模式中被称为工厂方法模式

简单工厂模式改造

下面我们从代码的角度进行分析。4S店卖车首先要有车,这里只取日产部分车型逍客,轩逸和天籁。

代码片段1 日产车父类,所有车型都继承此类。

/**
* 日产车
* @author coderzcr
*/
abstract class NissanCar {
String name;
void printCar(){
System.out.println(name+"汽车已制造完成");
}
}

代码片段2 车型:逍客

/**
* 车型:逍客
* @author coderzcr
*/
class Xtrail extends NissanCar {
Xtrail(){
this.name = "逍客";
}
}

代码片段3 车型:轩逸

/**
* 车型:轩逸
* @author coderzcr
*/
class Sylphy extends NissanCar {
Sylphy(){
this.name = "轩逸";
}
}

代码片段4 车型:天籁

/**
* 车型:天籁
* @author coderzcr
*/
class Altima extends NissanCar {
Altima(){
this.name="天籁";
}
}

有了具体的车型要求,我们需要对不同车型建立工厂。

代码片段5 日产工厂父类,所有工厂都继承此类。

/**
* 日产车工厂
* @author coderzcr
*/
public abstract class NissanCarFactory {
/**
* 生产汽车
*/
abstract NissanCar createCar() ; }

代码片段6 天籁工厂。

/**
* 天籁工厂
* @author coderzcr
*/
public class AltimaFactory extends NissanCarFactory {
@Override
NissanCar createCar() {
return new Altima();
}
}

代码片段7 逍客工厂。

/**
* 逍客工厂
* @author coderzcr
*/
public class XtrailFactory extends NissanCarFactory {
@Override
NissanCar createCar() {
return new Xtrail();
}
}

代码片段8 轩逸工厂。

/**
* 轩逸工厂
* @author coderzcr
*/
public class SylphyFactory extends NissanCarFactory {
@Override
NissanCar createCar() {
return new Sylphy();
}
}

图1 多工厂类图

工厂方法模式定义

工厂方法模式(Factory Method Pattern)又称为工厂模式,也叫虚拟构造器(Virtual Constructor)模式或者多态工厂(Polymorphic Factory)模式,它属于类创建型模式。在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。

工厂父类(日产车工厂)

工厂子类(轩逸工厂、天籁工厂、逍客工厂)

即产品的制造分配给子工厂,缓解单一工厂的压力。

工厂方法模式结构

图2 工厂方法模式结构

工厂方法模式包含如下角色:

  • Product:抽象产品
  • ConcreteProduct:具体产品
  • Factory:抽象工厂
  • ConcreteFactory:具体工厂

工厂方法模式分析

优点分析

  • 工厂方法模式的优点包括简单工厂方法模式的优点:用户只需要关心所需产品对应的工厂,无须关心创建细节,甚至无须知道具体产品类的类名。
  • 而且解决了简单工厂存在的不符合开闭原则问题,

    在系统中加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品就可以了。这样,系统的可扩展性也就变得非常好,完全符合“开闭原则”。

缺点分析

添加新产品时,需要添加一个具体工厂和具体产品,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。

参考文献

2. 工厂方法模式(Factory Method Pattern) — Graphic Design Patterns

大白话工厂方法模式(Factory Method)的更多相关文章

  1. 乐在其中设计模式(C#) - 工厂方法模式(Factory Method Pattern)

    原文:乐在其中设计模式(C#) - 工厂方法模式(Factory Method Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 工厂方法模式(Factory Method Pa ...

  2. 【设计模式】工厂方法模式 Factory Method Pattern

    在简单工厂模式中产品的创建统一在工厂类的静态工厂方法中创建,体现了面形对象的封装性,客户程序不需要知道产品产生的细节,也体现了面向对象的单一职责原则(SRP),这样在产品很少的情况下使用起来还是很方便 ...

  3. 工厂方法模式-Factory Method(Java实现)

    工厂方法模式-Factory Method 工厂方法模式定义一个用于创建对象的接口,让子类决定实例化哪一个类.工厂方法让实例化的具体内容交给子类工厂来进行. 本文中的例子是这样的. 生产一个身份证, ...

  4. 二十四种设计模式:工厂方法模式(Factory Method Pattern)

    工厂方法模式(Factory Method Pattern) 介绍定义一个用于创建对象的接口,让子类决定将哪一个类实例化.Factory Method使一个类的实例化延迟到其子类. 示例有SqlMes ...

  5. 设计模式-03工厂方法模式(Factory Method Pattern)

    插曲.简单工厂模式(Simple Factory Pattern) 介绍工厂方法模式之前,先来做一个铺垫,了解一下简单工厂模式,它不属于 GoF 的 23 种经典设计模式,它的缺点是增加新产品时会违背 ...

  6. IOS设计模式浅析之工厂方法模式(Factory Method)

    概述 在软件系统中,经常面临着“某个对象”的创建工作,由于需求的变化,这个对象的具体实现经常面临着剧烈的变化,但是它却拥有比较稳定的接口. 如何隔离出这个易变对象的变化,使得系统中“其它依赖该对象的对 ...

  7. 大话设计模式--工厂方法模式 Factory Method -- C++实现

    1. 工厂方法模式 定义一个用于创建对象的接口, 让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类. 和简单工厂模式相比: A: 简单工厂模式最大的优点在于工厂类中包含有必要的逻辑判断, ...

  8. 六个创建模式之工厂方法模式(Factory Method Pattern)

    问题: 在使用简单工厂模式的时候,如果添加新的产品类,则必需修改工厂类,违反了开闭原则. 定义: 定义一个用于创建对象的接口,让子类决定具体实例化哪个产品类.此时工厂和产品都具有相同的继承结构,抽象产 ...

  9. 工厂方法模式(Factory Method Pattern)

    工厂方法模式概述 工厂方法模式是为了弥补简单工厂模式的不足并且继承它的优点而延生出的一种设计模式,属于GoF中的一种.它能更好的符合开闭原则的要求. 定义:定义了一个用于创建对象的接口,但是让子类决定 ...

  10. 设计模式之工厂方法模式(Factory Method Pattern)

    一.工厂方法模式的诞生 在读这篇文章之前,我先推荐大家读<设计模式之简单工厂模式(Simple Factory Pattern)>这篇文档.工厂方法模式是针对简单工厂模式中违反开闭原则的不 ...

随机推荐

  1. 【java面试】框架篇之Spring

    1.你如何理解Spring? 具体来说Spring是一个轻量级的容器,用于管理业务相关对象的.核心功能主要为:IOC,AOP,MVC. IOD:控制反转,将对象的创建过程交给容器,让容器管理对象的生命 ...

  2. Java lambda 表达式常用示例

    实体类 package com.lkb.java_lambda.dto; import lombok.Data; /** * @program: java_lambda * @description: ...

  3. mysqldump 备份与恢复操作记录

     一,参数详解 [root@bug ~]# ? mysqldump --master-data[=#] mysqldump导出数据时,当这个参数的值为1的时候,mysqldump出来的文件就会包括CH ...

  4. C++使用类调用CUDA核函数

    正如CUDA C所称,CUDA对C语言进行了很好的扩展,直接使用C语言可以非常简单方便的调用CUDA核函数.但是当想使用C++的类成员函数直接调用核函数是不可行的,第一,核函数不能作为类的成员函数,第 ...

  5. Arduino系列之中断函数

    今天我将简单记录中断函数 函数分为外部中断和定时中断 外部中断的定义:一般由外设发出中断请求,如:键盘中断.打印机中断.外部中断需外部中断源发出中断请求才能发中断. 定时中断的定义:是指主程序在运行一 ...

  6. HanLP《自然语言处理入门》笔记--6.条件随机场与序列标注

    笔记转载于GitHub项目:https://github.com/NLP-LOVE/Introduction-NLP 6. 条件随机场与序列标注 本章介绍一种新的序列标注模型条件随机场.这种模型与感知 ...

  7. SpringMVC 参数映射与文件上传

    handler参数映射: 接下来就是Spring的各个处理细节了,无论框架如何疯转其实我们处理请求的流程是不变的,设计到的操作也是固定的,举个例子,当我们要实现一个登陆功能时: 创建一个用于处理登录请 ...

  8. 【动手学pytorch】线性回归

    代码及解释 错题整理

  9. 程序为什么开头总是PUSH EBP

    因为对堆栈的操作寄存器有EBP和ESP两个.EBP是堆栈的基址,ESP一直指向栈顶(只要有PUSH动作,ESP就自动减小,栈的生长方向从大往小,不需要手动改变ESP.)所以要压入EBP,然后再用EBP ...

  10. ubuntu16.04+Opencv3.4.0安装(slam版)

    本文记录ubuntu下安装opencv过程,步骤来自 opencv官网可以对照官网步骤:https://docs.opencv.org/3.4.0/d7/d9f/tutorial_linux_inst ...