理解设计模式中的单例模式一文中介绍了创建型模式中最为简单的一种:单例模式,并推荐了几种可以在实际生产中使用的线程安全的形式。本文将继续介绍创建型模式中的工厂方法模式和抽象工厂模式,同样使用代码和类图来直观的理解工厂模式究竟是什么,及如何使用。希望大家阅读完之后,对于工厂模式所涉及的三种形式有一个初步的理解,以便在后续的使用工具中做到举一反三。

本文仅限自己的理解,如果错误,欢迎大家指出交流。


文章目录

  • 前言
  • 工厂模式
    • 1. 简单工厂模式
    • 2. 工厂方法模式
    • 3. 抽象工厂模式
  • 总结

前言

工厂模式属于创建型模式中的一种,它的目的仍然是用于创建对象实例,不过它为实例的创建了一种新的思路。顾名思义,工厂模式就是将实例的创建交给类对应的工厂类去做,而对象类本身只负责和对象相关的一些其他工作。工厂模式可以分为:

  • 简单工厂模式
  • 工厂方法模式
  • 抽象工厂模式

工厂模式

1. 简单工厂模式


520刚刚过去,美妆类的产品恐怕是不少男生在礼物挑选时一种不会出错的选择。当然,美妆类的产品有很多,例如口红、唇膏、眼影、腮红、高光……我们以其中的口红(Lip Stick)为例来理解工厂模式。假设Forlogen想要买一支口红,但他不知道口红有YSL、TF、Dior、Chanel、Guerlain、Givenchy等等众多的品牌,他应该怎么做呢?一种最简单的方法就是去咨询身边的朋友,询问之后朋友推荐了YSL、TF和Dior,最后他就去准备购买口红。

如果他选择去综合类的美妆店或是直播间去进行购买,这里使用的其实就是简单工厂模式,如何理解呢?Forlogen在购买口红时只知道那三个牌子,因此,他开始咨询导购员:

Forlogen:请问有YSL的口红嘛?

导购员:有,请问你需要那个色号的呢?

Forlogen:你来介绍一下吧

导购员:blabla……

Forlogen:那TF的有什么推荐嘛?

导购员:blabla……

Forlogen:有没有Dior呢?

导购员:不好意思,本店里暂时没有Dior的口红,……

最终Forlogen可能会根据导购员的推荐选择购买了其中的几支,安全的度过了平凡的一天~

下面我们就用代码来解释下上面的整体流程,从而看一下它是如何体现简单工厂模式的思想的。首先创建一个接口LipStick,接口中只有一个抽象方法show()用于显示购买的口红的信息。

public interface LipStick {void show();
}

每一个品牌的口红的实现类都需要实现这个接口,假设美妆店里只有YSL的小金条和TF的黑管:

public class YSL implements LipStick {@Overridepublic void show(){System.out.println("YSL -- Small gold bars");}
}
public class TF implements LipStick{@Overridepublic void show(){System.out.println("TOM FORD -- Black bars");}
}

那么创建一个工厂类Store表示美妆店,通过Store中的getLipStick()就可以根据品牌名购买各种口红:

public class Store {public static LipStick getLipStick(String brand){if (brand.equalsIgnoreCase("YSL")){return new YSL();} else if (brand.equalsIgnoreCase("TF")){return new TF();} else {return null;}}
}

Forlogen购买时只需要和导购说口红的品牌即可,而不需要知道口红是怎么来的。

public class Consumer {public static void main(String[] args) {LipStick ls = Store.getLipStick("YSL");if (ls == null) {System.out.println("no this lipstick...");} else {ls.show();}}
}

最后Forlogen选择了YSL的小金条。

YSL -- Small gold bars

最后,我们来分析一下简单工厂模式有什么优缺点:

  • 优点:易于理解,使用简单
  • 缺点:如果此时店里引入了一个新的品牌,那么此时除了新建口红的实现类之外,还需要在Store类中多加一组if-else判断。而则就违反了七大设计原则中的开闭原则:对扩展开放对修改关闭

因此,简单工厂模式通常用来生产同一品类中的任意产品,但是对于新产品需要修改已有的代码。

2. 工厂方法模式


如果Forlogen是一个没有朋友的人,那么他就无法通过他人来知道哪些品牌的口红比较好。因此,他选择直接去商场一层的专柜进行购买,这里使用的就是工厂方法模式。此时,口红的购买不再是通过咨询综合美妆店里的导购员,而是直接通过专柜进行购买。而且如果此时商场引入了一个新的品牌,只需要在商场中建立一个新的专柜即可。

这里同样有口红的接口LipStick,以及YSL和TF的实现类:

public interface LipStick {void show();
}
public class YSL implements LipStick{@Overridepublic void show() {System.out.println("YSL -- Small gold bars");}
}
public class TF implements LipStick{@Overridepublic void show() {System.out.println("TOM FORD -- Black bars");}
}

此时,口红是直接通过专柜来进行购买,因此需要创建每个品牌对应的工厂类。首先同样创建一个工厂的接口LipStickFactory,接口中只有一个方法LipStickFactory

public interface LipStickFactory {LipStick getLipStick();
}
public class YSL_Factory implements LipStickFactory{@Overridepublic YSL getLipStick(){return new YSL();}
}
public class TF_Factory implements LipStickFactory{@Overridepublic TF getLipStick(){return new TF();}
}

Forlogen直接去想要的专柜进行购买即可,如果商场中设置了某品牌的专柜,那么就可以购买,否则就无法购买。

public class Consumer {public static void main(String[] args) {TF_Factory tf_factory = new TF_Factory();TF lipStick = tf_factory.getLipStick();lipStick.show();YSL lipStick1 = new YSL_Factory().getLipStick();lipStick1.show();}
}

最后Forlogen购买了YSL的小金条和TF的黑管。

TOM FORD -- Black bars
YSL -- Small gold bars

最后来分析一个工厂方法模式的优缺点:

  • 优点:工厂方法模式为每个产品都设置了专门的工厂类,用户直接通过各个类对应的工厂进行购买,满足开闭原则
  • 缺点:每新增一个商品就需要新建一个对象类和对应的工厂类,代码量成倍的增加

因此,工厂方法模式通常用来生产同一品类中的固定产品,它支持任意的增加新产品。

3. 抽象工厂模式


如果此时Forlogen觉得只买口红太单一,他决定再买些其他的美妆产品。对于每一个品牌来说,他们不只是生产口红,同样会生产香水、气垫等其他相关的产品。因此,工厂方法模式就不能很好的满足需求,需要对工厂模式做进一步的抽象。假设现在有口红和香水(perfume)两类产品,按照工厂模式的整体思想,我们首先需要创建它们各自的工厂接口。例如口红的工厂接口LipStickFactory,它包含两个抽象方法:

  • setColor():它用来表示购买的口红的色号,是正红、番茄色、豆沙色还是其他的色号
  • serEffect():它用来表示口红的质感,是珠光、雾面哑光还是丝绒哑光等
public interface LipStickFactory {void setColor();void setEffect();
}

同样有香水的接口PerfumeFactory,它其中包含三个方法分别用于表示香水的前调、中调和后调。

public interface PerfumeFactory {void setTopNote();void setMiddleNot();void setBaseNote();
}

对于YSL来说,它的口红类要实现LipStickFactory接口,香水类要实现PerfumeFactory接口,并重写其中对应的抽象方法

public class YSL_LipStick implements LipStickFactory{@Overridepublic void setColor() {System.out.println("Red...");  // 正红}@Overridepublic void setEffect() {System.out.println("shimmer..."); // 珠光}
}
// YSL LIBRE自由之水
public class YSL_Perfume implements PerfumeFactory{@Overridepublic void setTopNote() {System.out.println("citrus"); // 橙花,柑橘}@Overridepublic void setMiddleNot() {System.out.println("lavender..."); // 薰衣草 橙花}@Overridepublic void setBaseNote() {System.out.println("vanilla...");  // 香草  龙涎香}
}

TF的口红类和香水类也要实现相应的接口,并重写其中的方法

public class TF_LipStick implements LipStickFactory{@Overridepublic void setColor() {System.out.println("cameo brown...");  // 豆沙色}@Overridepublic void setEffect() {System.out.println("matte...");  // 雾面哑光}
}
public class Tf_Perfume implements PerfumeFactory{@Overridepublic void setTopNote() {System.out.println("rose...");  // 玫瑰}@Overridepublic void setMiddleNot() {System.out.println("lavender..."); // 薰衣草 橙花}@Overridepublic void setBaseNote() {System.out.println("citrus"); // 橙花,柑橘}
}

而此时购买某一品牌的商品时仍然是从专柜来购买,但是此时的专柜不仅卖口红,还买香水。因此,首先需创建工厂的工厂接口ProductFactory,其中的抽象方法表示一个美妆产品专柜应该卖哪些产品。

public interface ProductFactory {LipStickFactory getLipStick();PerfumeFactory getPerfume();
}

YSL和TF对应的工厂类就需要实现这个抽象工厂接口,并重写其中的方法

public class YSL_Factory implements ProductFactory
{@Overridepublic LipStickFactory getLipStick() {return new YSL_LipStick();}@Overridepublic PerfumeFactory getPerfume() {return new YSL_Perfume();}
}
public class TF_Factory implements ProductFactory{@Overridepublic LipStickFactory getLipStick() {return new TF_LipStick();}@Overridepublic PerfumeFactory getPerfume() {return new Tf_Perfume();}
}

此时,Forlogen通过综合类的专柜不仅可以购买到口红,还可以购买香水。

public class Consumer {public static void main(String[] args) {TF_Factory tf_factory = new TF_Factory();LipStickFactory lipStick = tf_factory.getLipStick();lipStick.setColor();lipStick.setEffect();System.out.println("----------------");YSL_Factory ysl_factory = new YSL_Factory();PerfumeFactory perfume = ysl_factory.getPerfume();perfume.setTopNote();perfume.setMiddleNot();perfume.setBaseNote();}
}

最后Forlogen购买了一支TF家哑光质感的豆沙色口红和一支YSL的LIBRE系列的香水。

cameo brown...
matte...
----------------
citrus
lavender...
vanilla...

最后同样来总结一下抽象工厂模式的优缺点:

  • 优点:抽象工厂模式首先具有工厂方法模式的优点,即它可以任意的增加新产品,只需要实现相应的工厂接口即可。此外,它最主要的优点是可以在类的内部对产品族进行约束,即通过工厂可以生产同一品牌不同类别的产品
  • 缺点:使用抽象工厂模式扩展较为麻烦,如果此时新增了一类产品,那么要创建产品的工厂接口,每个品牌的新产品类要实现该接口,此外抽象工厂接口和每个品牌的抽象接口都需要更新。因此,如果产品族中产品类品较多且固定时,抽象工厂方法是一个较好的选择

总结

不同的工厂模式的实现方式有各自对应的较为合适的应用场景,但彼此的划分并不是绝对的,因此,在实际的使用过程中,我们应该根据具体的应用场景来选则具体的方式进行使用。

理解设计模式中的工厂模式相关推荐

  1. 理解设计模式中的原型模式

    原型模式 May the force be with you 文章目录 1. 前言 2. 案例 1. 前言 原型模式从根本上来说就是Java中的对象克隆,针对于对象的浅拷贝和深拷贝,Java中提供了两 ...

  2. C#设计模式(2)——简单工厂模式

    一.引言 这个系列也是自己对设计模式的一些学习笔记,希望对一些初学设计模式的人有所帮助的,在上一个专题中介绍了单例模式,在这个专题中继续为大家介绍一个比较容易理解的模式--简单工厂模式. 二.简单工厂 ...

  3. 虚无空间java下载_Java进阶篇设计模式之二 ----- 工厂模式

    前言 在上一篇中我们学习了单例模式,介绍了单例模式创建的几种方法以及最优的方法.本篇则介绍设计模式中的工厂模式,主要分为简单工厂模式.工厂方法和抽象工厂模式. 简单工厂模式 简单工厂模式是属于创建型模 ...

  4. getinstance方法详解_二、设计模式总览及工厂模式详解

    二.架构师内功心法之设计模式 2.架构师内功心法之设计模式 2.1.课程目标 1.通过对本章内容的学习,了解设计模式的由来. 2.介绍设计模式能帮我们解决哪些问题. 3.剖析工厂模式的历史由来及应用场 ...

  5. 设计模式之简单工厂模式(Simply Factory)摘录

    从设计模式的类型上来说,简单工厂模式是属于创建型模式,又叫静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一.简单工厂模式是由一个工厂对象决定创建出哪一种 ...

  6. 设计模式之简单工厂模式(静态工厂方法)

    模式定义: 从设计模式的类型上来说,简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一. 简单工厂模式是由一个工厂对象 ...

  7. php的类图怎么生成_PHP设计模式之简单工厂模式

    PHP设计模式之简单工厂模式 先从简单工厂入门,不管是面试还是被他人面试,在问到设计模式的时候,大多数人都会提到工厂模式.毫无疑问,工厂相关的几种模式在设计模式中是最出名的也是应用比较广泛的一种模式. ...

  8. [python实现设计模式]-3.简单工厂模式-触宝开放平台

    预备知识: 开放封闭原则(Open-Closed Principle OCP) Software entities(classes,modules,functions etc) should open ...

  9. 软件设计模式“单例模式”和“工厂模式”

    软件设计模式"单例模式"和"工厂模式" 单例模式 什么是单例模式 单例模式的实现方式有哪些 单例模式的优缺点 单例模式的应用场景 总结 工厂模式 什么是工厂模式 ...

最新文章

  1. 几种和生成网络相似的纠缠网络(接近人脑)
  2. USACO 3.2 kimbits DP
  3. 实现 ASP.NET WebForm Client
  4. p1417 烹调方案_Java 8的烹调方式–拼图项目
  5. 建模元件有哪些在MapleSim中
  6. Java核心篇之泛型--day5
  7. CSDN-markdown编辑器的使用方法大全
  8. Codeforces Round #879 (Div. 2) C. Short Program
  9. CCIE学习(40)—— OSPF设计与LSA类型(三)
  10. MySQL索引分类入门
  11. 无线网卡在使用过程突然不好使的解决方法,Deepin Linux 15.9与Windows 10双系统
  12. 微信全球MBA创新大赛Roadshow最终站火爆中欧
  13. linux运行roon,Roon + HQPlayer + NAA + 解码 网线直连方案
  14. 各种类型数据库以及其适用场景
  15. Namenode HA原理详解
  16. 【Apache Spark 】第 2 章下载 Apache Spark并开始使用
  17. 用tikz画球坐标系下的体积微元
  18. ES索引生命周期管理ILM
  19. php 公众号 欢迎,关注公众号的欢迎语怎么设置?公众号欢迎语怎么加链接?
  20. c语言去掉文件中重复单词,awk脚本 使用awk去掉重复的单词

热门文章

  1. [JSP]错误信息、错误处理
  2. my-mind在线思维导图软件
  3. hyperledger-fabric第一天 Fabric环境搭建
  4. 教你用PS制作gif动态图
  5. Linux界面和字体大小调整
  6. 实验记录 | 6/29
  7. 高可用解决方案:同城双活?异地双活?异地多活?怎么实现?
  8. Euler characteristic
  9. java银生宝接口开发_银生宝代付和网关渠道
  10. (2)QlikView安装