问题:

在使用简单工厂模式的时候,如果添加新的产品类,则必需修改工厂类,违反了开闭原则。

定义:

定义一个用于创建对象的接口,让子类决定具体实例化哪个产品类。此时工厂和产品都具有相同的继承结构,抽象产品类与抽象工厂对应,具体的产品类和具体的工厂类对应。工厂方法模式又称为:工厂模式(Factory Pattern)、虚拟构造器模式(Virtual Constructor Pattern)、多态工厂模式(Polymorphic Factory Pattern)等。

结构图:

  • Product:抽象产品类,是所有具体产品的超类型,封装了具体产品的公共方法。
  • ConcreteProduct:具体产品类,实现了抽象产品类的接口,和具体工厂一一对应。
  • Factory:抽象工厂类,定义了返回抽象产品类的工厂方法,是工厂方法模式的核心。
  • ConcreteFactory:具体工厂类,实现了抽象工厂定义的工厂方法,由客户端直接调用,返回其对应的具体产品类。

注意:

  • 为了让系统有更好的灵活性和可扩展性,可以使用XML技术和反射技术让客户端通过配置文件指定具体工厂类。

  • 可以在抽象工厂中定义多个重载的工厂方法,包含不同的业务逻辑,来满足对不同产品对象的需求。例如可以传入数据库配置信息,文件配置信息等。

interface LoggerFactory {
public Logger createLogger();
public Logger createLogger(String args);
public Logger createLogger(Object obj);
}
class DatabaseLoggerFactory implements LoggerFactory {
public Logger createLogger() {
//使用默认方式连接数据库,代码省略
Logger logger = new DatabaseLogger();
//初始化数据库日志记录器,代码省略
return logger;
} public Logger createLogger(String args) {
//使用参数args作为连接字符串来连接数据库,代码省略
Logger logger = new DatabaseLogger();
//初始化数据库日志记录器,代码省略
return logger;
} public Logger createLogger(Object obj) {
//使用封装在参数obj中的连接字符串来连接数据库,代码省略
Logger logger = new DatabaseLogger();
//使用封装在参数obj中的数据来初始化数据库日志记录器,代码省略
return logger;
}
}
  • 还可以由工厂直接调用具体产品的业务方法,而隐藏工厂创建具体实例的方法。
abstract class LoggerFactory {
//在工厂类中直接调用日志记录器类的业务方法writeLog()
public void writeLog() {
Logger logger = this.createLogger();
logger.writeLog();
} public abstract Logger createLogger();
}

优点:

  • 利用工厂的工厂方法类创建具体的实例,隐藏了具体实例的创建细节,无需知道具体实例的类名,只需关心对应工厂。
  • 加入新的产品类是,只需要同时加入工厂类就可以实现扩展。如果利用反射和XML技术,不需要修改任何源码,符合“开闭原则”

缺点:

  • 系统中类的个数显著增加,不利于系统的维护,增加系统编译和运行的开销。

适用场景

  • 具体产品类数目不多,客户不需要知道具体产品类的详细信息,只需要知道具体对应的工厂。

实例:

FactoryMethodPattern.java

六个创建模式之工厂方法模式(Factory Method Pattern)的更多相关文章

  1. 使用C# (.NET Core) 实现简单工厂(Simple Factory) 和工厂方法设计模式 (Factory Method Pattern)

    本文源自深入浅出设计模式. 只不过我是使用C#/.NET Core实现的例子. 前言 当你看见new这个关键字的时候, 就应该想到它是具体的实现. 这就是一个具体的类, 为了更灵活, 我们应该使用的是 ...

  2. 23种设计模式之工厂方法(Factory Method Pattern)

    工厂方法 前面我们学习了简单工厂,发现一个问题就是简单工厂集合了矛盾,为了解决这个问题我们针对每一种产品提供一个工厂类.通过不同的工厂实例来创建不同的产品实例.在同一等级结构中,支持增加任意产品这种设 ...

  3. 设计模式---对象创建模式之工厂方法模式(Factory Method)

    前提:“对象创建”模式 通过“对象创建”模式绕开new,来避免对象创建(new)过程中所导致的紧耦合(依赖具体类),从而支持对象创建的稳定.它是接口抽象之后的第一步工作. 典型模式(表现最为突出) 工 ...

  4. 设计模式学习之工厂方法(Factory Method,创建型模式)(2)

    接着上一讲中的简单工厂继续讲解,假如我们有了需要采集新的水果梨子,如果我们使用简单工厂中的方式的话,就会新增一个Pear类,然后实现Fruit类,然后修改FruitFactory类中获取实例的方法 g ...

  5. Java设计模式(2)——创建型模式之工厂方法模式(Factory Method)

    一.概述 上一节[简单工厂模式]介绍了通过工厂创建对象以及简单的利弊分析:这一节来看看工厂方法模式对类的创建 工厂方法模式: 工厂方法与简单工厂的不同,主要体现在简单工厂的缺点的改进: 工厂类不再负责 ...

  6. JAVA设计模式(01):创建型-工厂模式【工厂方法模式】(Factory Method)

    简单工厂模式尽管简单,但存在一个非常严重的问题.当系统中须要引入新产品时,因为静态工厂方法通过所传入參数的不同来创建不同的产品,这必然要改动工厂类的源码,将违背"开闭原则".怎样实 ...

  7. 工厂方法(Factory Method)模式

    一.工厂方法(Factory Method)模式 工厂方法(FactoryMethod)模式是类的创建模式,其用意是定义一个创建产品对象的工厂接口,将实际创建工作推迟的子类中. 工厂方法模式是简单工厂 ...

  8. 设计模式的征途—3.工厂方法(Factory Method)模式

    上一篇的简单工厂模式虽然简单,但是存在一个很严重的问题:当系统中需要引入新产品时,由于静态工厂方法通过所传入参数的不同来创建不同的产品,这必定要修改工厂类的源代码,将违背开闭原则.如何实现新增新产品而 ...

  9. 小菜学习设计模式(三)—工厂方法(Factory Method)模式

    前言 设计模式目录: 小菜学习设计模式(一)—模板方法(Template)模式 小菜学习设计模式(二)—单例(Singleton)模式 小菜学习设计模式(三)—工厂方法(Factory Method) ...

  10. Java 工厂模式(一)— 工厂方法(Factory Method)模式

    一.工厂方法(Factory Method)模式: 1.什么是工厂方法模式? 工厂方法模式是类的创建型模式,又叫做虚拟构造子模式或者多态工厂模式.它的意义是创建产品对象的工厂接口,将实际创建工作推迟到 ...

随机推荐

  1. 初探设计:Java接口和抽象类何时用?怎么用?

    今天犯了个错: “接口变动,伤筋动骨,除非你确定只有你一个人在用”.哪怕只是throw了一个新的Exception.哈哈,这是我犯的错误. 一.接口和抽象类 类,即一个对象. 先抽象类,就是抽象出类的 ...

  2. Selenium自动化测试项目案例实践公开课

    Selenium自动化测试项目案例实践公开课: http://gdtesting.cn/news.php?id=55

  3. LeetCode:5_Longest Palindromic Substring | 最长的回文子串 | Medium

    题目: Given a , and there exists one unique longest palindromic substring. 解题思路:1.简单思路:暴力破解法,时间复杂度O(n^ ...

  4. Java知多少(完结篇)

    Java知多少(1)语言概述 Java知多少(2)虚拟机(JVM)以及跨平台原理 Java知多少(3) 就业方向 Java知多少(4)J2SE.J2EE.J2ME的区别 Java知多少(5) Java ...

  5. Adroid学习系列-入门(1)

    1.  安装 安装Eclipse,安装Adroid插件.安装Adroid SDK. 2.  项目目录说明 2.1.       建立Adroid项目 与一般的Java项目一样 )src文件夹是项目的所 ...

  6. Errors running builder 'JavaScript Validator' on project

    builders去掉JavaScript Validator. 如图: 参考文献: [1]http://www.cnblogs.com/enshrineZither/p/4062248.html

  7. 高性能JavaScript-JS脚本加载与执行对性能的影响

    在web产品优化准则中,很重要的一条是针对js脚本的加载和执行方式的优化.本篇文章简单描述一下其中的优化准则. 1. 脚本加载优化 1.1 脚本位置对性能的影响 优化页面加载性能的原则之一是将scri ...

  8. uboot命令及内核启动参数

        修改:mw [内存地址] [值] [长度] 例如:mw 0x02000000 0 128 表示修改地址为0x02000000~0x02000000+128的内存值为0. 显示:md [内存地址 ...

  9. 设计模式之Interator模式(1)

    interator是java容器遍历的一种手段,当然遍历容易你可以使用普通的for(;;)或者for(Object o : new Arraylist<Object>()),都是可以的. ...

  10. UWP开发入门(十七)——判断设备类型及响应VirtualKey

    蜀黍我做的工作跟IM软件有关,UWP同时会跑在电脑和手机上.电脑和手机的使用习惯不尽一致,通常我倾向于根据窗口尺寸来进行布局的变化,但是特定的操作习惯是依赖于设备类型,而不是屏幕尺寸的,比如聊天窗口的 ...