定义

此模式的核心精神是封装类中不变的部分,提取其中个性化善变的部分为独立类,通过依赖注入以达到解耦、复用和方便后期维护拓展的目的。

定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。

和简单工厂模式的对比

工厂方法模式对简单工厂模式进行了抽象。有一个抽象的Factory类(可以是抽象类和接口),这个类将不再负责具体的产品生产,而是只制定一些规范,具体的生产工作由其子类去完成。在这个模式中,工厂类和产品类往往可以依次对应。

具体来说就是,简单工厂是一个可以创建任意对象的超级工厂,而工厂方法定义了一个抽象工厂,不同类型的产品对应不同的工厂实现类,在简单工厂的基础上进一步的抽象。

UML

优点

在工厂方法中,用户只需要知道所要产品的具体工厂,无须关系具体的创建过程,甚至不需要具体产品类的类名。

在系统增加新的产品时,我们只需要添加一个具体产品类和对应的实现工厂,无需对原工厂进行任何修改,很好地符合了“开闭原则”。

缺点

每次增加一种新类型的产品时,都需要增加多个具体类和对象实现工厂,是的系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。

应用场景

  1. 对于某个产品,调用者清楚地知道应该使用哪个具体工厂服务,实例化该具体工厂,生产出具体的产品来。Java Collection中的iterator() 方法即属于这种情况。
  2. 只需要一种产品,而不想知道也不需要知道究竟是哪个工厂为生产的,即最终选用哪个具体工厂的决定权在生产者一方,它们根据当前系统的情况来实例化一个具体的工厂返回给使用者,而这个决策过程这对于使用者来说是透明的。
  3. 一个类不知道它所需要的对象的类。在工厂方法模式中,我们不需要具体产品的类名,我们只需要知道创建它的具体工厂即可。
  4. 一个类通过其子类来指定创建那个对象。在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,在程序运行时,子类对象将覆盖父类对象,从而使得系统更容易扩展。
  5. 将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时再动态指定。

示例

实现一个创建不同产品的工厂。

Java

 public class Main
{
public static void main(String[] args)
{
//工厂抽象对象
Creator factroy;
//实例化指定的工厂对象
factroy = new ConcreteCreator();
//产品接口
IProduct product;
//创建指定的产品并使用
product = factroy.createProduct(ProductA.class);
product.doSomething();
product = factroy.createProduct(ProductB.class);
product.doSomething();
} /**
* 产品接口
*/
public static interface IProduct
{
void doSomething();
} /**
* 产品A
*/
public static class ProductA implements IProduct
{
@Override
public void doSomething()
{
System.out.println("ProductA doSomething!");
}
} /**
* 产品B
*/
public static class ProductB implements IProduct
{
@Override
public void doSomething()
{
System.out.println("ProductB doSomething!");
}
} /**
* 抽象工厂
*/
public static abstract class Creator
{
/**
* 这里通过反射得到指定类型的实例, 实际使用中可以根据需求来实现
*/
public abstract <T extends IProduct> T createProduct(Class<T> c);
} /**
* 具体的工厂实现类
*/
public static class ConcreteCreator extends Creator
{
@Override
public <T extends IProduct> T createProduct(Class<T> c)
{
T product = null;
try
{
product = (T) Class.forName(c.getName()).newInstance();
}
catch (Exception e)
{
e.printStackTrace();
}
return product;
}
}
}

创建类模式(一):工厂方法(Factory Method)的更多相关文章

  1. Spring 通过工厂方法(Factory Method)来配置bean

    Spring 通过工厂方法(Factory Method)来配置bean 在Spring的世界中, 我们通常会利用bean config file 或者 annotation注解方式来配置bean. ...

  2. 抽象工厂(Abstract Factory),工厂方法(Factory Method),单例模式(Singleton Pattern)

    在谈工厂之前,先阐述一个观点:那就是在实际程序设计中,为了设计灵活的多态代码,代码中尽量不使用new去实例化一个对象,那么不使用new去实例化对象,剩下可用的方法就可以选择使用工厂方法,原型复制等去实 ...

  3. 创建型模式(二) 工厂方法模式(Factory Method)

    一.动机(Motivation) 在软件系统创建过程中,经常面临着"某个对象"的创建工作:由于需求的变化,这个对象(的具体实现)经常面临着剧烈的变化,但是它却拥有比较稳定的接口.如 ...

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

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

  5. [设计模式-创建型]工厂方法(Factory Method)

    概括 名称 Factory Method 结构 动机 定义一个用于创建对象的接口,让子类决定实例化哪一个类.Factory Method 使一个类的实例化延迟到其子类. 适用性 当一个类不知道它所必 ...

  6. 设计模式——工厂方法(Factory Method)

    定义一个用于创建对象的接口,让子类决定实例化哪一个类.工厂方法使一个类的实例化延迟到其子类. ——DP UML类图 模式说明 抽象业务基类 实际业务类的公共基类,也是工厂要创建的所有对象的父类,这部分 ...

  7. Headfirst设计模式的C++实现——工厂方法(Factory Method)

    引用原书的一句话:所有的工厂模式都用来封装对象的创建,工厂方法模式通过让子类决定该创建的对象是什么来达到封装的目的. Pizza类及其派生类与上一例相同 PizzaStore.h #ifndef _P ...

  8. 设计模式二: 工厂方法(Factory Method)

    简介 工厂方法模式是创建型模式的一种, 核心结构有四个角色: 抽象工厂,具体工厂,抽象产品,具体产品; 实现层面上,该模式定义一个创建产品的接口,将实际创建工作推迟到具体工厂类实现, 一个产品对应一个 ...

  9. 工厂方法 Factory Method

    背景:有一个应用框架,它可以向用户显示多个文档.在这个框架中,两个主要的抽象是类Application和Document.这两个类都是抽象的.客户必须通过它们的子类来做与举替应用相关的实现. 分析:因 ...

  10. GoF23种设计模式之创建型模式之工厂方法模式

    一.概述 定义一个用于创建对象的接口,让子类去决定实例化哪个类.工厂方法将一个类的实例化延迟至其子类. 二.适用性 1.当一个类不知道它所必须创建的对象的类的时候. 2.当一个类希望由其子类来指定它所 ...

随机推荐

  1. UVa 12186 Another Crisis

    题意: 给出一个树状关系图,公司里只有一个老板编号为0,其他人员从1开始编号.除了老板,每个人都有一个直接上司,没有下属的员工成为工人. 工人们想写一份加工资的请愿书,只有当不少于员工的所有下属的T% ...

  2. css,html命名规则

    css,html命名规则 页头: header 登录条: loginBar 标志: logo 侧栏: sideBar 广告: banner 导航: nav 子导航: subNav 菜单: menu 子 ...

  3. Java Web编程的主要组件技术——JDBC

    参考书籍:<J2EE开源编程精要15讲> JDBC(Java DataBase Connectivity)是Java Web应用程序开发的最主要API之一.当向数据库查询数据时,Java应 ...

  4. codevs 1218 疫情控制

    啊好烦这道题.... 基本思路网上都有. 注意的一点是在匹配的时候,如果有军队的来源没有被匹配到,那么就先匹配这个来源.(因为不花钱). 不过数据好水.... #include<iostream ...

  5. 运维角度浅谈MySQL数据库优化(转)

    一个成熟的数据库架构并不是一开始设计就具备高可用.高伸缩等特性的,它是随着用户量的增加,基础架构才逐渐完善.这篇博文主要谈MySQL数据库发展周期中所面临的问题及优化方案,暂且抛开前端应用不说,大致分 ...

  6. 我的ECshop二次开发从零开始

    我是一个EC新手,EC就算做再多的模板,肯定也满足不了我们的需要,更何况各行有各行的门道,EC统一做出来的模板也不一定合适于我们这个行业用,因此,只有我们真正掌握了自己做模板,修改模板的功夫,才能真正 ...

  7. Arc Engine 中添加气泡提示框

    一.在ArcMap中的定位操作 已知若干点的经纬度坐标,要求在地图中进行定位: 1.通过Tool >Add X Y data 定位点,注意选择地理坐标系下的wgs 1984坐标系: 2.定位后的 ...

  8. Filezilla中文字符文件看不到或显示乱码的解决办法

    Filezilla确实是跨平台的好软件,可之前我就在ubuntu下郁闷为什么看坛子FTP里竟然是空的.最近换MAC版的FZ结果还是这样就奇怪了. 后来想Filezilla应该是支持字符集转换的,所以在 ...

  9. UNDO表空间设置

    flashback query和flashback table都是以用UNDO表空间的内容来进行恢复数据 查看undo内容保存的时间: SQL> show parameter undo_re N ...

  10. 你今天Python了吗?(下)

    在体验了wxPython的强大之后,让我们把注意力集中到Twisted上来.在C++的世界里,你会发现一个很棒的网络应用框架,那就是ACE了:在Python的地盘,Twisted则是在网络应用框架中当 ...