设计模式(1) - 工厂方法

问题描述

一个接口(如下图的Product)可能有多种实现方式。程序逻辑在实例化这种类型/接口的具体类(如下图的ConcreteProduct)的时候,如果直接使用{new ConcreteProduct()}的方式来撰写;当需求变更的时候,程序需要使用另外一个子类(例如SubProduct)来替换该类的时候,所有使用{new ConcreteProduct()}的地方都需要修改。这种代码的特征是:没有封装好程序的一个可能的“变化点”(即具体对象创建的可变性)。工厂方法模式把{new ClassName(...)}这种对象实例化的代码封装到一个相对稳定的Factory Method中,让一个可能变化的逻辑(类如何实例化)对于客户而言稳定不变。

工厂方法模式

如下图所示,工厂方法模式为具体对象(ConcreteProduct)的创建提供一个间接层,客户端通过一个稳定的对象创建接口(即工厂方法: Product* ConcreteCreator::CreateProduct())来实例化该对象。当程序逻辑需要使用一个不同于ConcreteProduct的类来定义程序行为时,只需要修改ConcreteCreator类的方法Product* ConcreteCreator::CreateProduct()的实现就可以了。虽然客户端硬编码了一个Factory Method类(即ConcreteCreator类),相对于到处修改{new ClassName(...)},这种硬编码方式让变化集中到了一个变化点,让程序的修改局限在一个可控的范围。


讨论

工厂方法模式的价值在于:

  • 封装了程序一个可能的变化点:如何创建一个具体对象。本模式定义了一个对象创建的接口,客户端使用这个接口来创建对象,保证了客户端逻辑的稳定性
  • 解除了类的创建者(即类的客户端逻辑)和具体类名字的耦合:不管接口如何子类化,修改ConcreteCreator的具体实现就可以创建不同的具体类
  • 强化了基于接口编程原则:工厂方法返回的通常是一个抽象类型(基类指针或者接口引用),这要求客户端逻辑基于这些接口/抽象类型来构建,而不是基于具体类型

下面的代码展示了MFC中使用本模式的一个例子:CreateObject()本质上就是一个工厂方法,可以创建一个不带参数的,支持动态创建的MFC对象。虽然没有抽象基类,但是已经体现了工厂方法模式的本质:通过一个稳定的接口来创建对象,返回一个抽象类型;让对象的创建者和对象的具体类型解耦。

#define _DECLARE_DYNCREATE(class_name)     \
    _DECLARE_DYNAMIC(class_name)           \
    static CObject* PASCAL CreateObject();

#define IMPLEMENT_DYNCREATE(class_name, base_class_name)        \
    CObject* PASCAL class_name::CreateObject()                  \
        { return new class_name; }                              \
    IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF, \
        class_name::CreateObject)                               \
        ...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值