概述:

属于创建型设计模式,需要生成的对象叫做产品 ,生成对象的地方叫做工厂 。

使用场景:

在任何需要生成复杂对象的地方,都可以使用工厂方法模式。 
直接用new可以完成的不需要用工厂模式

下面将介绍五种工厂类:

简单(静态)工厂:

一个栗子: 
我喜欢吃面条,抽象一个面条基类,(接口也可以),这是产品的抽象类

public abstract class INoodles {/*** 描述每种面条啥样的*/public abstract void desc();
}

先来一份兰州拉面(具体的产品类

public class LzNoodles extends INoodles {@Overridepublic void desc() {System.out.println("兰州拉面 上海的好贵 家里才5 6块钱一碗");}
}

程序员加班必备也要吃泡面(具体的产品类):

public class PaoNoodles extends INoodles {@Overridepublic void desc() {System.out.println("泡面好吃 可不要贪杯");}
}

还有我最爱吃的家乡的干扣面(具体的产品类):

public class GankouNoodles extends INoodles {@Overridepublic void desc() {System.out.println("还是家里的干扣面好吃 6块一碗");}
}

准备工作做完了,我们来到一家“简单面馆”(简单工厂类),菜单如下:

public class SimpleNoodlesFactory {public static final int TYPE_LZ = 1;//兰州拉面public static final int TYPE_PM = 2;//泡面public static final int TYPE_GK = 3;//干扣面public static INoodles createNoodles(int type) {switch (type) {case TYPE_LZ:return new LzNoodles();case TYPE_PM:return new PaoNoodles();case TYPE_GK:default:return new GankouNoodles();}}
}

简单面馆就提供三种面条(产品),你说你要啥,他就给你啥。这里我点了一份干扣面:

/*** 简单工厂模式*/INoodles noodles = SimpleNoodlesFactory.createNoodles(SimpleNoodlesFactory.TYPE_GK);noodles.desc();

特点

1 它是一个具体的类,非接口 抽象类。有一个重要的create()方法,利用if或者 switch创建产品并返回。

2 create()方法通常是静态的,所以也称之为静态工厂

缺点

1 扩展性差(我想增加一种面条,除了新增一个面条产品类,还需要修改工厂类方法)

2 不同的产品需要不同额外参数的时候 不支持。

另一种简单工厂(反射):

利用反射Class.forName(clz.getName()).newInstance()实现的简单工厂:

public class StaticNoodlesFactory {/*** 传入Class实例化面条产品类** @param clz* @param <T>* @return*/public static <T extends INoodles> T createNoodles(Class<T> clz) {T result = null;try {result = (T) Class.forName(clz.getName()).newInstance();} catch (Exception e) {e.printStackTrace();}return result;}
}

点菜时:

/*** 另一种简单工厂* 利用Class.forName(clz.getName()).newInstance()*/System.out.println("=====另一种简单工厂利用Class.forName(clz.getName()).newInstance()======" +"\n个人觉得不好,因为这样和简单的new一个对象一样,工厂方法应该用于复杂对象的初始化" +"\n 这样像为了工厂而工厂");//兰州拉面INoodles lz = StaticNoodlesFactory.createNoodles(LzNoodles.class);lz.desc();//泡面INoodles pm = StaticNoodlesFactory.createNoodles(PaoNoodles.class);pm.desc();

特点

1 它也是一个具体的类,非接口 抽象类。但它的create()方法,是利用反射机制生成对象返回,好处是增加一种产品时,不需要修改create()的代码

缺点

这种写法粗看牛逼,细想之下,不谈reflection的效率还有以下问题:

1 个人觉得不好,因为Class.forName(clz.getName()).newInstance()调用的是无参构造函数生成对象,它和new Object()是一样的性质,而工厂方法应该用于复杂对象的初始化 ,当需要调用有参的构造函数时便无能为力了,这样像为了工厂而工厂。

2 不同的产品需要不同额外参数的时候 不支持。

多方法工厂(常用)

使用方法二 三实现的工厂,都有一个缺点:不同的产品需要不同额外参数的时候 不支持。

而且如果使用时传递的type、Class出错,将不能得到正确的对象,容错率不高。

而多方法的工厂模式为不同产品,提供不同的生产方法,使用时 需要哪种产品就调用该种产品的方法,使用方便、容错率高

工厂如下:

public class MulWayNoodlesFactory {/*** 模仿Executors 类* 生产泡面** @return*/public static INoodles createPm() {return new PaoNoodles();}/*** 模仿Executors 类* 生产兰州拉面** @return*/public static INoodles createLz() {return new LzNoodles();}/*** 模仿Executors 类* 生产干扣面** @return*/public static INoodles createGk() {return new GankouNoodles();}
}

使用时:

        /*** 多方法静态工厂(模仿Executor类)*/System.out.println("==============================模仿Executor类==============================" +"\n 这种我比较青睐,增加一个新面条,只要去增加一个static方法即可,也不修改原方法逻辑");INoodles lz2 = MulWayNoodlesFactory.createLz();lz2.desc();INoodles gk2 = MulWayNoodlesFactory.createGk();gk2.desc();

源码撑腰环节

查看java源码:java.util.concurrent.Executors类便是一个生成Executor 的工厂 ,其采用的便是 多方法静态工厂模式

例如ThreadPoolExecutor类构造方法有5个参数,其中三个参数写法固定,前两个参数可配置,如下写。

public static ExecutorService newFixedThreadPool(int nThreads) {return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());}

又如JDK想增加创建ForkJoinPool类的方法了,只想配置parallelism参数,便在类里增加一个如下的方法(通过重载增加):

    public static ExecutorService newWorkStealingPool(int parallelism) {return new ForkJoinPool(parallelism,ForkJoinPool.defaultForkJoinWorkerThreadFactory,null, true);}

这个例子可以感受到工厂方法的魅力了吧:方便创建 同种类型的 复杂参数 对象

普通工厂

普通工厂就是把简单工厂中具体的工厂类,划分成两层:抽象工厂层+具体的工厂子类层。(一般->特殊)

面条工厂(抽象工厂类),作用就是生产面条:

public abstract class NoodlesFactory {public abstract INoodles create();
}

兰州拉面工厂 (具体工厂子类):

public class LzFactory extends NoodlesFactory {@Overridepublic INoodles create() {return new LzNoodles();}
}

泡面工厂 (具体工厂子类):

public class PaoFactory extends NoodlesFactory {@Overridepublic INoodles create() {return new PaoNoodles();}
}

最爱的干扣面工厂 (具体工厂子类):

public class GankouFactory extends NoodlesFactory {@Overridepublic INoodles create() {return new GankouNoodles();}
}

使用时:

        /*** 普通工厂方法:*/System.out.println("===========================普通工厂方法==============================" +"\n 这种要多写一个类,不过更面向对象吧 = = ,实际中我更倾向于使用【模仿Executor类】的方式");NoodlesFactory factory1 = new GankouFactory();INoodles gk3 = factory1.create();gk3.desc();

普通工厂与简单工厂模式的区别:

可以看出,普通工厂模式特点:不仅仅做出来的产品要抽象, 工厂也应该需要抽象

工厂方法使一个产品类的实例化延迟到其具体工厂子类.

工厂方法的好处就是更拥抱变化。当需求变化,只需要增删相应的类,不需要修改已有的类

而简单工厂需要修改工厂类的create()方法,多方法静态工厂模式需要增加一个静态方法。

缺点:

引入抽象工厂层后,每次新增一个具体产品类,也要同时新增一个具体工厂类,所以我更青睐 多方法静态工厂。

抽象工厂:

以上介绍的工厂都是单产品系的。抽象工厂是多产品系 (貌似也有产品家族的说法)。

举个例子来说,每个店(工厂)不仅仅卖面条,还提供饮料卖。 
提供饮料卖,饮料是产品,先抽象一个产品类,饮料:

public abstract class IDrinks {/*** 描述每种饮料多少钱*/public abstract void prices();
}

然后实现两个具体产品类: 
可乐:

public class ColaDrinks extends IDrinks {@Overridepublic void prices() {System.out.println("可乐三块五");}
}

屌丝还是多喝水吧:

public class WaterDrinks extends IDrinks {@Overridepublic void prices() {System.out.println("和我一样的穷鬼都喝水,不要钱~!");}
}

抽象饭店,无外乎吃喝(抽象工厂类):

public abstract class AbstractFoodFactory {/*** 生产面条** @return*/public abstract INoodles createNoodles();/*** 生产饮料*/public abstract IDrinks createDrinks();
}

兰州大酒店(具体工厂类):

public class LzlmFoodFactory extends AbstractFoodFactory {@Overridepublic INoodles createNoodles() {return new LzNoodles();//卖兰州拉面
    }@Overridepublic IDrinks createDrinks() {return new WaterDrinks();//卖水
    }
}

KFC(具体工厂类):

public class KFCFoodFactory extends AbstractFoodFactory {@Overridepublic INoodles createNoodles() {return new PaoNoodles();//KFC居然卖泡面
    }@Overridepublic IDrinks createDrinks() {return new ColaDrinks();//卖可乐
    }
}

使用:

        /*** 抽象工厂方法:*/System.out.println("==============================抽象方法==============================" +"\n 老实说,以我这一年的水平我体会不到抽象工厂有何巨大优势,所以在我这里我没有想到很好的使用场景。希望以后在慢慢体会吧。");AbstractFoodFactory abstractFoodFactory1 = new KFCFoodFactory();abstractFoodFactory1.createDrinks().prices();abstractFoodFactory1.createNoodles().desc();abstractFoodFactory1= new LzlmFoodFactory();abstractFoodFactory1.createDrinks().prices();abstractFoodFactory1.createNoodles().desc();

小结:

将工厂也抽象了,在使用时,工厂和产品都是面向接口编程,OO(面向对象)的不得了。

缺点

但是将工厂也抽象后,有个显著问题,就是类爆炸了。而且每次拓展新产品种类,例如不仅卖吃卖喝,我还想卖睡,提供床位服务,这需要修改抽象工厂类,因此所有的具体工厂子类,都被牵连,需要同步被修改

老实说,以我这一年的水平我体会不到抽象工厂有何巨大优势,所以在我这里我没有想到很好的使用场景。

个人总结和使用场景

一句话总结工厂模式:方便创建 同种产品类型的 复杂参数 对象

工厂模式重点就是适用于 构建同产品类型(同一个接口 基类)的不同对象时,这些对象new很复杂,需要很多的参数,而这些参数中大部分都是固定的,so,懒惰的程序员便用工厂模式封装之。 
(如果构建某个对象很复杂,需要很多参数,但这些参数大部分都是“不固定”的,应该使用Builder模式)

为了适应程序的扩展性,拥抱变化,便衍生出了 普通工厂、抽象工厂等模式。

转载于:https://www.cnblogs.com/callyblog/p/8117116.html

设计模式(三) 工厂模式相关推荐

  1. 设计模式(三)--工厂模式

    1.1简单工厂模式 1.1.1看一个具体的需求:看一个披萨的项目:要便于披萨种类的扩展,要便于维护 披萨的种类很多(比如 GreekPizz.CheesePizz 等) 披萨的制作有 prepare, ...

  2. 设计模式之工厂模式(三)

    上一次我们已经通过代码,简单的认识了工厂方法模式,具体的思路请移步到设计模式之工厂模式(二),进行查看.这次,让我们通过设计模式的思想,来好好认识下工厂方法模式. 创建者和产品 所有工厂模式都用来封装 ...

  3. JavaScript设计模式--简单工厂模式例子---XHR工厂

    JavaScript设计模式--简单工厂模式例子---XHR工厂 第一步,Ajax操作接口(目的是起一个接口检测作用) (1)引入接口文件 //定义一个静态方法来实现接口与实现类的直接检验 //静态方 ...

  4. 三角形圆形创建与擦除java_设计模式---------------简单工厂模式

    设计模式---------------简单工厂模式 一.题目(Question) 使用简单工厂模式设计一个可以创建不同几何形状(如圆形.方形和三角形等)的绘图工具,每个几何图形都要有绘制draw()和 ...

  5. Java 设计模式之工厂模式(二)

    原文地址:Java 设计模式之工厂模式(二) 博客地址:http://www.extlight.com 一.背景 本篇内容是 Java 设计模式创建型模式的第二篇.上一篇主题为 <Java 设计 ...

  6. php工厂模式和单例模式,php 设计模式之工厂模式、单例模式、注册树模式

    php 设计模式之工厂模式.单例模式.注册树模式 在软件工程中,创建型设计模式承担着对象创建的职责,尝试创建适合程序上下文的对象,对象创建设计模式的产生是由于软件工程设计的问题,具体说是向设计中增加复 ...

  7. 教你如何一篇博客读懂设计模式之—--工厂模式

    一篇博客读懂设计模式之-工厂模式 工厂模式在我们日常开发的时候经常用到,相信大家都有了一定的了解,工厂模式是一种创建对象的设计模式,它提供一种创建对象的最佳方式. 主要过程是: 定义一个创建对象的接口 ...

  8. 系统架构技能之设计模式-抽象工厂模式

    一.上篇回顾 上篇我们主要讲述了简单工厂模式和工厂模式.并且分析了每种模式的应用场景和一些优缺点,我们现在来回顾一下: 简单工厂模式:一个工厂负责所有类型对象的创建,不支持无缝的新增新的类型对象的创建 ...

  9. java设计模式之工厂模式(UML类图分析+代码详解)

    大家好,我是一名在算法之路上不断前进的小小程序猿!体会算法之美,领悟算法的智慧~ 希望各位博友走过路过可以给我点个免费的赞,你们的支持是我不断前进的动力!! 加油吧!未来可期!! 本文将介绍java设 ...

  10. java 设计模式 路由器_java设计模式2————工厂模式

    java设计模式2----工厂模式 1.工厂模式介绍: 1.1.实现了创建者与调用者的分离 1.2.详细分类: 简单工厂模式 工厂方法模式 抽象工厂模式 1.3.所遵循的OOP原则: 开闭原则:对扩展 ...

最新文章

  1. 03_TF2 Guide、文档清单(数据输入、估计器、保存模型、加速器、性能调优等)、TF2库和扩展库(TensorBoard、数据集、TensorFlow Hub、概率和统计分析库、图像处理库)
  2. 不可变的基础架构,热部署和JVM
  3. DS树+图综合练习--构建邻接表
  4. 【python】有意思的python小项目GitHub地址汇总
  5. 分词相关技术(转载)
  6. Postgres不同数据库间访问
  7. C++调用C#编写的com组件方法
  8. pycharm 默认pip安装位置_为什么电脑所有软件默认安装位置都是C盘?
  9. Modern Python Cookbook》(Python经典实例)笔记 2.3 编写长行代码
  10. 论项目管理中的需求管理
  11. win10 C盘优化清理
  12. 解决征信中心密码控件无法安装
  13. 性价比超高的51单片机学习板与开发板
  14. linux下创建1G的文件,Linux/UNIX: 使用 dd 命令创建 1GB 大小的二进制
  15. github提交代码:schannel: failed to receive handshake, SSL/TLS connection failed
  16. 如何在C语言中把int*转化为char*
  17. java能搞底层吗_彻底搞清楚Java并发 (二) 底层实现
  18. vert.x java post请求无法接收到post请求body中的参数
  19. python的脑安装了ffmpeg_python脚本实现音频m4a格式转成MP3格式
  20. 【锐捷无线】边缘感知配置

热门文章

  1. Yii框架怎么寻找对应视图
  2. 【CIKM2020】如何更为合适地评测推荐算法? Top-N物品推荐算法评测设置回顾
  3. 【收藏】这个时候才是最好的自学时间!深度学习-机器学习-GNN-NLP等AI课程超级大列表汇总,拿走不谢...
  4. 命名实体识别数据集构建
  5. 数据科学包12-实例1:股票数据分析
  6. python---python3 获取当前路径及os.path.dirname的使用;os.path.abspath(__file__)用法及意义
  7. Django2.0中URL的路由机制
  8. 算法刷题指南,来自GitHub 68.8k star的硬核算法教程
  9. 谁说五月是没有收获的季节
  10. argparse模块