设计模式系列之工厂模式

设计模式一直是面向对象软件设计中最重要的一个领域,围绕设计模式讨论的话题也是数不胜数,其中GOF代表的23种设计模式更是经典之著。这个系列中我将会从自己的理解出发,阐述每种设计模式的思想,作用和利弊。

一、 设计模式概念

要讲解设计模式,必然先要说清楚两个问题,

1.什么是设计模式?

2.为什么需要设计模式?

对于设计模式,GOF是这么定义的:设计模式是对被用来在特定场景下解决一般设计问题的类和相互通信的对象的描述,更特殊地,将之放到面向对象软件设计中来讲,设计模式可以被认为是实践中总结出的设计经验,是系统中会重复出现的设计。

所以设计模式可以帮助我们更加简单方便地复用成功的设计和体系结构,更具体地,为了获得最大限度地复用的关键在于新需求和已有需求发生变化时,系统设计有能力相应地改进,避免重新设计带来的巨大代价。每种设计模式都是通过确保系统以某种特定方式变化来获得这种可变能力,每一个设计模式允许系统结构的某个方面独立于其他方面,从而对某一种特殊变化具有适应性。

这就引出了选择设计模式的方法:首先考虑系统在哪些方面具有可变性,选择的设计模式不会因为这些可变因素而引起重新设计。GOF根据设计模式完成的任务类型将其分为了创建型,结构型和行为型三大类,创建型模式用于对象的创建,结构型模式用于处理类或者对象的组合;行为型模式描述类或对象怎样交互和分配职责。同时根据范围模式分为类模式和对象模式,类模式处理类和子类之间的关系,通过继承创建,是静态的,编译期就确定了;对象模式处理对象之间的关系,是动态的,运行时可变,具体分类如表格所示:


创建型


结构型


行为型


类模式


Factory method


Adapter


Interpreter

template method


对象模式


Abstract factory

builder

prototype

singleton


Adapter

bridge

composite

decorator

facade

flyweight

proxy


Chain of responsibility

command

iterator

mediator

memento

observer

state

strategy

visitor

创建型类模式将对象的部分创建工作延迟到子类,创建型对象模式则延迟到另一个对象中。结构型类模式使用继承机制来组合类,结构型对象模式则描述了对象的组合方式。行为类模式用继承描述算法和控制流,行为型对象模式则通过一组对象协作完成任务。另外我们将会看到,在部分类模式中,通过引入参数或者模板类型可以避免创建子类。

本系列以创建型模式的factory method模式开始,逐个介绍GOF的23种设计模式。

二、 factory method模式

如果一个类不知道需要创建的对象的类型时,如果当前希望子类来指定创建的对象类型时,如果希望将创建对象的职责委托给子类并将这一代理过程局部化时,就可以考虑使用factory method模式。

下面以一个例子来说明,这个例子也会在后续设计模式中多次提到,所以请读者先记住一下。现在要开发一个芯片设计的软件,可以在掩模上设计不同的图形。不同的掩模会有不同的参数,比如曝光方式,角度等,图形也可以会有很多种,在不影响理解的前提下我们假设只有圆形,矩形和三角形三种图形,在不同的掩模上画同一个图得到的效果是不一样的。对于同一种掩模,我们要得到一个可以画图的对象,至于画出的是圆形,矩形还是三角形,子类才能知道,掩模只能拿到接口。类设计图如下:

具体代码实现如下:

//mask.hpp
#ifndef MASK_HPP
#define MASK_HPP

class MaskFigure{
  public:
    virtual ~MaskFigure()=0;
  protected:
    MaskFigure();
};

class MaskRound:public MaskFigure {
  public:
    MaskRound();
    ~MaskRound();
};

class MaskRec:public MaskFigure {
  public:
    MaskRec();
    ~MaskRec();
};

class MaskTri:public MaskFigure {
  public:
    MaskTri();
    ~MaskTri();
};
#endif

//mask.cpp
#include <iostream>
#include "mask.hpp"

using std::cout;
using std::endl;

MaskFigure::MaskFigure() {

}

MaskFigure::~MaskFigure() {

}

MaskRound::MaskRound() {
  cout<<"Draw roundness on Mask"<<endl;
}

MaskRound::~MaskRound() {

}

MaskRec::MaskRec() {
  cout<<"Draw rectangle on Mask"<<endl;
}

MaskRec::~MaskRec() {

}

MaskTri::MaskTri() {
  cout<<"Draw triangle on Mask"<<endl;
}

MaskTri::~MaskTri() {

}
//factory.hpp
#ifndef MASKFACTORY_HPP
#define MASKFACTORY_HPP

#include "mask.hpp"

class FigureFactory {
 public:
  virtual ~FigureFactory()=0;
  virtual MaskFigure* CreateFigure()=0;
 protected:
  FigureFactory();
};

class RoundFactory:public FigureFactory {
 public:
  RoundFactory();
  ~RoundFactory();
  MaskRound* CreateFigure();
};

class RecFactory:public FigureFactory {
 public:
  RecFactory();
  ~RecFactory();
  MaskRec* CreateFigure();
};

class TriFactory:public FigureFactory {
 public:
  TriFactory();
  ~TriFactory();
  MaskTri* CreateFigure();
};
#endif

//factory.cpp
#include <iostream>
#include "factory.hpp"

using std::cout;
using std::endl;

FigureFactory::FigureFactory() {

}

FigureFactory::~FigureFactory() {

}

RoundFactory::RoundFactory() {
  cout<<"Init RoundFactory"<<endl;
}

RoundFactory::~RoundFactory() {

}

MaskRound* RoundFactory::CreateFigure() {
  return new MaskRound();
}

RecFactory::RecFactory() {
  cout<<"Init RecFactory"<<endl;
}

RecFactory::~RecFactory() {

}

MaskRec* RecFactory::CreateFigure() {
  return new MaskRec();
}

TriFactory::TriFactory() {
  cout<<"Init TriFactory"<<endl;
}

TriFactory::~TriFactory() {

}

MaskTri* TriFactory::CreateFigure() {
  return new MaskTri();
}

//main.cc
#include <memory>
#include <iostream>
#include "factory.hpp"
#include "factorytml.hpp"
using std::shared_ptr;
int main() {
  shared_ptr<RoundFactory> roundfac(new RoundFactory());
  shared_ptr<MaskRound>    mrd(roundfac->CreateFigure());

  shared_ptr<RecFactory> recfac(new RecFactory());
  shared_ptr<MaskRec>    mrc(recfac->CreateFigure());

  shared_ptr<TriFactory> trifac(new TriFactory());
  shared_ptr<MaskTri>    mti(trifac->CreateFigure());

  return 0;
}

roundness, rectangle和 triangle的构造都分别延迟到了 RoundFactory, RecFactory和TriFactory等派生类中完成,所以factory method模式又被成为虚构造函数。

不难发现,MaskFigure有几个子类, FigureFactory也需要对应数目的子类,MaskFigure增加一个图形时,FigureFactory就必须增加相应的工厂方法,有时候会产生太多子类,不易维护,c++中可以引入模板或者参数化来解决,从而避免创建子类。一个模板实现的factory method实例如下:

//factorytml.hpp
#ifndef FACTORYTML_HPP
#define FACTORYTML_HPP

#include <iostream>

using std::cout;
using std::endl;

class FigureFactoryTml {
 public:
  FigureFactoryTml(){ cout<<"Init FigureFactoryTml"<<endl; }
  ~FigureFactoryTml(){ }

  template<typename T>
  T* CreateFigure() {
    return new T();
  }
};
#endif
//main.cc
…
  shared_ptr<FigureFactoryTml>  fft(new FigureFactoryTml());
  shared_ptr<MaskRound>         mrdp(fft->CreateFigure<MaskRound>());
  shared_ptr<MaskRec>           mrcp(fft->CreateFigure<MaskRec>());
  shared_ptr<MaskTri>           mtip(fft->CreateFigure<MaskTri>());
…

(完)

时间: 2024-10-24 06:33:54

设计模式系列之工厂模式的相关文章

设计模式系列- 抽象工厂模式

抽象工厂是基于简单工厂发展而来的,通过抽象工厂,我们可以创建多种类型的工厂,并且依据具体业务需求而在具体工厂里面进行任意拼装组合. 介绍 在现实世界中,汽车制作行业有各种各样的工厂,每个工厂都需要具有生产轮胎.汽车引擎等部件的能力,但是针对具体的工厂,每个部件的生产又各不相同,所有在软件开发过程中,当我们为客户端制作各种各样的皮肤时,就可以参考这种设计模式. 类图描述 从上图我们可以发现,我们通过定义一个抽象工厂 AbstractFactory 来约束具体每种工厂所具备的能力,然后通过定义 IS

01.设计模式_简单工厂模式

转载自  http://www.cnblogs.com/zhili/p/SimpleFactory.html 一.引言 这个系列也是自己对设计模式的一些学习笔记,希望对一些初学设计模式的人有所帮助的,在上一个专题中介绍了单例模式,在这个专题中继续为大家介绍一个比较容易理解的模式--简单工厂模式. 二.简单工厂模式的介绍 说到简单工厂,自然的第一个疑问当然就是什么是简单工厂模式了? 在现实生活中工厂是负责生产产品的,同样在设计模式中,简单工厂模式我们也可以理解为负责生产对象的一个类, 我们平常编程

C#设计模式(2)——简单工厂模式

一.引言 这个系列也是自己对设计模式的一些学习笔记,希望对一些初学设计模式的人有所帮助的,在上一个专题中介绍了单例模式,在这个专题中继续为大家介绍一个比较容易理解的模式——简单工厂模式. 二.简单工厂模式的介绍 说到简单工厂,自然的第一个疑问当然就是什么是简单工厂模式了? 在现实生活中工厂是负责生产产品的,同样在设计模式中,简单工厂模式我们也可以理解为负责生产对象的一个类, 我们平常编程中,当使用”new”关键字创建一个对象时,此时该类就依赖与这个对象,也就是他们之间的耦合度高,当需求变化时,我

C#设计模式之三抽象工厂模式(AbstractFactory)【创建型】

原文:C#设计模式之三抽象工厂模式(AbstractFactory)[创建型] 一.引言 写了3篇有关设计模式的文章了,大家有了些反馈,说能从中学到一些东西,我感到很欣慰,那就继续努力.今天我要写第四个模式了,该模式叫抽象工厂.上一篇文章我们讲了[工厂方法]模式,它是为了解决[简单工厂]模式所面对的问题,它的问题就是:如果我们增加新的产品,工厂类的方法就要修改本身的代码,增加产品越多,其逻辑越复杂,同时这样的修改也是不符合[开放关闭原则OCP],对修改代码关闭,对增加代码开放.为了解决[简单工厂

Java设计模式之二工厂模式

在上一篇中我们学习了单例模式,介绍了单例模式创建的几种方法以及最优的方法.本篇则介绍设计模式中的工厂模式,主要分为简单工厂模式.工厂方法和抽象工厂模式. 简单工厂模式 简单工厂模式是属于创建型模式,又叫做静态工厂方法模式.简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例.调用只需要告诉工厂类所需要的类型,工厂类就会返回需要的产品类工厂的子类. 可以说是工厂模式中最简单的一种. 打个比方,我们在电脑经常玩游戏,我们只需要告诉电脑我们要玩什么游戏,电脑就会打开这个游戏,我们并不需要关心游戏是

二、设计模式总览及工厂模式详解

二.架构师内功心法之设计模式 2.架构师内功心法之设计模式 2.1.课程目标 1.通过对本章内容的学习,了解设计模式的由来. 2.介绍设计模式能帮我们解决哪些问题. 3.剖析工厂模式的历史由来及应用场景. 2.2.内容定位 不用设计模式并非不可以,但是用好设计模式能帮助我们更好地解决实际问题,设计模式最重要的 是解耦.设计模式天天都在用,但自己却无感知.我们把设计模式作为一个专题,主要是学习设计模式 是如何总结经验的,把经验为自己所用.学设计模式也是锻炼将业务需求转换技术实现的一种非常有效 的方

【设计模式】简单工厂模式

以面向对象的思想和简单工厂模式,写一个C++计算器程序,代码如下: #include <iostream> using namespace std; class Operation { public: Operation(double left, double right) { lhs = left; rhs = right; } const double GetLeft() const { return lhs; } const double GetRight() const { retur

设计模式之简单工厂模式

设计模式之简单工厂模式 动机:         不暴露实例化逻辑来创建对象.通过公共的接口创建新的对象.         这是一个简单的实现,客户端需要一个product,但是client不直接使用new对象,而是通过提供需要的对象信息来找factory得到新的product.         这个factory实例化一个具体的product并返回(转化成抽象的类),client段使用这个抽象的类而不用考虑它具体的实现. 应用举例:        也许工厂模式是使用最多的模式之一.举个例子,一个

设计模式之抽象工厂模式

抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类. 最大的好处便是易于交换产品系列,由于具体工厂类,在一个应用中只需在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需改变具体工厂即可使用不同的产品配置. 他使具体创建实例的过程与客户端分离,客户端是通过它们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离. 下面的代码还使用了反射与XML. 代码如下: using System; using System.Collections.Ge