设计模式之美:Factory Method(工厂方法)
索引
别名
- 虚构造器 (Virtual Constructor)
意图
定义一个用于创建目标对象的接口,让子类决定实例化哪一个目标类。
Factory Method 使一个类的实例化延迟到其子类。
Define an interface for creating an object, but let subclasses decide which class to instantiate.
Factory Method lets a class defer instantiation to subclasses.
结构
参与者
Product
- 定义工厂方法所创建的对象的接口(Interface)。
ConcreteProduct
- 实现 Product 接口。
Creator
- 声明工厂方法,该方法返回一个 Product 类型的对象。 Creator 也可以定义一个工厂方法的缺省实现,它返回一个缺省的 ConcreteProduct 对象。
- 可以调用工厂方法以创建一个 Product 对象。
ConcreteCreator
- 重定义(Override)工厂方法以创建一个 Product 对象。
适用性
在下列情况下可以使用 Factory Method 模式:
- 当一个类不知道它所必须创建的对象的类的时候。
- 当一个类希望由它的子类来指定它所创建的对象的时候。
- 当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。
缺点
- 客户可能仅仅为了创建一个特定的 ConcreteProduct 对象,就不得不创建 Creator 的子类。
效果
- 为子类提供挂钩
- 连接平行的类层次
相关模式
- Abstract Factory 经常用工厂方法来实现。
- Factory Method 通常在 Template Method 中被调用。
- Prototype不需要创建 Creator 的子类。但是,它们通常要求一个针对 Product 类的 Initialize 操作。Creator 使用 Initialize 来初始化对象,而 Factory Method 不需要这样的操作。
命名约定
使用命名约定是一个好习惯,它可以清楚地说明你正在使用工厂方法。(Convention over Configuration)
例如,总是声明那些定义为工厂方法的抽象操作为 CreateProduct()。
实现
实现方式(一):Creator 类是一个抽象类并且不提供它所声明的工厂方法的实现。
需要子类来定义实现,因为没有合理的缺省实现。它避免了不得不实例化不可预见类的问题。
namespace FactoryMethodPattern.Implementation1
{
public abstract class AbstractOrInterfaceOfCreator
{
public abstract AbstractOrInterfaceOfProduct CreateProduct();
} public abstract class AbstractOrInterfaceOfProduct
{
} public class ConcreteCreator : AbstractOrInterfaceOfCreator
{
public override AbstractOrInterfaceOfProduct CreateProduct()
{
return new ConcreteProduct();
}
} public class ConcreteProduct : AbstractOrInterfaceOfProduct
{
} public partial class Test
{
public void Case1()
{
AbstractOrInterfaceOfCreator creator = new ConcreteCreator();
AbstractOrInterfaceOfProduct product = creator.CreateProduct();
}
}
}
实现方式(二):Creator 类是一个具体类而且为工厂方法提供一个缺省的实现。
具体的 Creator 主要因为灵活性才使用工厂方法。它所遵循的准则是,“用一个独立的操作创建对象,这样子类才能重定义它们的创建方法”。这条准则保证了子类的设计者能够在必要的时候改变父类所实例化的对象的类。
namespace FactoryMethodPattern.Implementation2
{
public class ConcreteCreator
{
public virtual AbstractOrInterfaceOfProduct CreateProduct()
{
return new ConcreteProduct();
}
} public abstract class AbstractOrInterfaceOfProduct
{
} public class ConcreteProduct : AbstractOrInterfaceOfProduct
{
} public partial class Test
{
public void Case2()
{
ConcreteCreator creator = new ConcreteCreator();
AbstractOrInterfaceOfProduct product = creator.CreateProduct();
}
}
}
实现方式(三):参数化工厂方法。
使用参数化工厂方法可以创建多种产品。工厂方法采用一个标识要被创建的对象种类的参数。
namespace FactoryMethodPattern.Implementation3
{
public enum ProductCategory
{
GoodProduct,
BadProduct,
} public class ConcreteCreator
{
public virtual AbstractOrInterfaceOfProduct CreateProduct(ProductCategory category)
{
switch (category)
{
case ProductCategory.GoodProduct:
return new ConcreteGoodProduct();
case ProductCategory.BadProduct:
return new ConcreteBadProduct();
default:
throw new NotSupportedException();
}
}
} public abstract class AbstractOrInterfaceOfProduct
{
} public class ConcreteGoodProduct : AbstractOrInterfaceOfProduct
{
} public class ConcreteBadProduct : AbstractOrInterfaceOfProduct
{
} public partial class Test
{
public void Case3()
{
ConcreteCreator creator = new ConcreteCreator();
AbstractOrInterfaceOfProduct product = creator.CreateProduct(ProductCategory.GoodProduct);
}
}
}
实现方式(四):使用模板以避免创建子类。
使用C#中的泛型实现工厂方法。
namespace FactoryMethodPattern.Implementation4
{
public abstract class AbstractOrInterfaceOfCreator
{
public abstract AbstractOrInterfaceOfProduct CreateProduct();
} public class GenericConcreteCreator<T> : AbstractOrInterfaceOfCreator
where T : AbstractOrInterfaceOfProduct, new()
{
public AbstractOrInterfaceOfProduct CreateProduct()
{
return new T();
}
} public abstract class AbstractOrInterfaceOfProduct
{
} public class ConcreteGoodProduct : AbstractOrInterfaceOfProduct
{
} public class ConcreteBadProduct : AbstractOrInterfaceOfProduct
{
} public partial class Test
{
public void Case3()
{
AbstractOrInterfaceOfCreator creator1 = new GenericConcreteCreator<ConcreteGoodProduct>();
AbstractOrInterfaceOfCreator creator2 = new GenericConcreteCreator<ConcreteBadProduct>();
AbstractOrInterfaceOfProduct product1 = creator1.CreateProduct();
AbstractOrInterfaceOfProduct product2 = creator2.CreateProduct();
}
}
}
《设计模式之美》为 Dennis Gao 发布于博客园的系列文章,任何未经作者本人同意的人为或爬虫转载均为耍流氓。
设计模式之美:Factory Method(工厂方法)的更多相关文章
- 面向对象设计模式纵横谈:Factory Method 工厂方法模式(笔记记录)
从耦合关系谈起 耦合关系直接决定着软件面对变化时的行为 -模块与模块之间的紧耦合使得软件面对变化时,相关模块都要随之更改 -模块与模块之间的松耦合使得软件面对变化时,一些模块更容易被替换或者更改,但其 ...
- c++ 设计模式8 (Factory Method 工厂方法)
5. “对象创建”类模式 通过“对象创建”类模式绕开new,来避免对象创建(new)过程中所导致的紧耦合(依赖具体类),从而支持对象创建的稳定.它是接口抽象之后的第一步工作. 5.1 工厂方法 动机: ...
- C#面向对象设计模式纵横谈——5.Factory Method 工厂方法模式(创建型模式)
动机 (Motivation) 在软件系统中,经常面临着“某个对象”的创建工作; 由于需求的变化,这个对象经常面临着剧烈的变化,但是它却拥有比较稳定的接口. 如何应对这种变化?如何提供一种“封装机制” ...
- Factory Method 工厂方法模式
Factory method工厂方法模式是一种实现了“工厂”概念的面向对象设计模式.就像其他创建型模式一样,它也是处理在不指定对象具体类型的情况下创建对象的问题.工厂方法模式的实质是“定义一个创建对象 ...
- 设计模式04: Factory Methord 工厂方法模式(创建型模式)
Factory Methord 工厂方法模式(创建型模式) 从耦合关系谈起耦合关系直接决定着软件面对变化时的行为 -模块与模块之间的紧耦合使得软件面对变化时,相关的模块都要随之变更 -模块与模块之间的 ...
- Java设计模式:Factory Method(工厂方法)模式
概念定义 工厂方法(Factory Method)模式,又称多态工厂(Polymorphic Factory)模式或虚拟构造器(Virtual Constructor)模式.工厂方法模式通过定义工厂抽 ...
- 设计模式之 Factory Method 工厂方法
看到的比较有意思的一篇描述工厂方法的文章. http://www.codeproject.com/Articles/492900/From-No-Factory-to-Factory-Method 总 ...
- 设计模式C++学习笔记之五(Factory Method工厂方法模式)
工厂方法模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中.核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的 ...
- Factory Method(工厂方法)-对象创建型模式
1.意图 定义一个用于创建对象的接口,让子类决定实例化哪一个类.Factory Method使一个类的实例化延迟到其子类. 2.动机 框架使用抽象类定义和维护对象之间的关系.这些对象的创建通常也由框架 ...
- 3.Factory Method 工厂方法模式(创建型模式)
1.定义: 定义一个用于创建对象的接口,让子类决定实例化哪一个类.Factory Method使得一个类的实例化延迟到子类. 2.实现代码如下: /// <summary> /// 工厂方 ...
随机推荐
- netstat大量time_wait连接
http://chembo.iteye.com/blog/1503770 http://www.2cto.com/os/201007/54067.html http://blog.csdn.net/d ...
- java并发编程_CountDownLanch(倒计数锁存器)应用场景
使用介绍: 一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待. 用给定的计数 初始化 CountDownLatch.由于调用了 countDown() 方法,所以在 ...
- linux shell学习笔记
一 变量 声明变量: my_var='ddd'使用变量: ${my_var}设置为只读变量: readonly my_var删除变量: unset my_var 注意只读变量不能被删除 变量类型:( ...
- ajax实现文件下载
前台: <html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"> ...
- docker进程管理
docker进程管理:http://www.open-open.com/lib/view/open1455412749917.html 写的太好!!!!示例很清楚,很全面!! 我做个summary吧. ...
- easyui1.32 各种问题汇总
问题一 场景:tab切换,每个tab里用div放一个dataGrid,默认display:none隐藏,当display:'block'的时候,dataGrid会显示不全,仅显示一条线. 解决方法:切 ...
- Visual Studio 换皮肤
通过字体和颜色修改 Visual Studio 提供了修改配色的入口,你完全可以根据自己的喜好进行自定义,下面就通过该方法把编辑器背景设置成 “豆沙绿”. 选择 工具 / 选项 / 环境 / 字体和颜 ...
- codevs4919 线段树练习4
4919 线段树练习4 时间限制: 1 s 空间限制: 128000 KB 题目描述 Description 给你N个数,有两种操作 1:给区间[a,b]内的所有数都增加X 2:询问区 ...
- error in opening zip file 1 错误
项目部署服务启动时会出现: error in opening zip file 1 错误 原来是不同服务器编译过的jar包直接下载后发布有问题,重新上传本地编译好的lib下面的jar包后,启动服务,正 ...
- MATLAB - 图像基本操作
1.读入一幅图像 I = imread('lena.jpg');%给出图片路径即可,I是一个三维矩阵 J = rgb2gray(I); figure, imshow(I), figure, imsho ...