问题:

假设我们要开发一个游戏--打怪物,首先,游戏有分等级,假设有初级,中级两个个等级(就不用flappy bird模式了,那个比较特殊,对一个玩家来说是难以具有持久吸引力的!),不同的等级怪物也是不一样的,我们不妨假设初级为怪物A1, B1,中级为怪物A2,B2。如图所示:

设计:

那么根据面向对象思想,我们来考虑一下应该怎么设计程序结构,首先不同等级的怪物要由不同的对象来产生,即相当于不同等级的怪物也应该由不同类型的工厂来生产。但不同等级的怪物都是怪物,它们具有某些共同点,应该继承自同一个父怪物类。同样,不同等级的工厂也应该继承自同一个父工厂类。我们称这样的父工厂类和父怪物类为AbstractFactory和AbstractProduct。这个模式成为AbstractFactory模式。

AbstractFactory模式的典型结构图为:

其实这里我们还应该考虑的一个问题是我们为什么要增加一个AbstractFactory类,在factory模式中,是不需要AbstractFactory而是直接由factory类来生产product的,即如下的结构:

但我们从第二个图可以很容易看出,这里的factory只有一个,只能生产同一个等级的怪物。

首先,我们用factory的是为了解决两个问题:

1)、提高内聚和松耦合

2)、父类中无法知道要实例化哪个具体的子类(具体看下面)

这里引出了factory模式的两个重要功能:

1)定义创建对象的接口,封装了对象的创建;
2)使得具体化类的工作延迟到了子类中。

我们可以看出,第二个图的结构解决了第一个问题,即它使得我们能够规范的使用一个接口来初始化类,我们想象一下,为了达到多态,我们经常抽象出一个基类,然后很多不同的子类指向这个基类,这样我们在需要创建子类的对象的时候我们就必须知道具体的子类的名字,这样带来很多问题,如名称多而乱等,还有可拓展性问题。但有一个相同的接口的话,接口内部的修改不影响用户,可拓展性增强了,而且用户无需知道具体的子类的名字就可以创建对象了。

但是,第二个图的结构无法解决第二个问题。第二个图的模式只有一种基类。那么这时我们就要用到第一个图所显示的AbstractFactory 模式了。

AbstractFactory 模式通过将一组对象的额创建封装到一个用于创建对象的类(ConcreteFactory)中,这样,我们可以根据不同的ConcreteFactory类来实例化不同类型的子对象。并且,维护这样一个创建类总比维护n多相关对象的创建过程要简单的多。

下面我们来看看具体的代码实现:

 //Product.h

 #ifndef PRODUCT_H
#define PRODUCT_H class AbstractProductA{
public:
virtual ~AbstractProductA();
protected:
AbstractProductA();
private:
}; class AbstractProductB
{
public:
virtual ~AbstractProductB();
protected:
AbstractProductB();
private:
}; class ProductA1: public AbstractProductA{
public:
ProductA1();
~ProductA1();
protected:
private:
}; class ProductA2:public AbstractProductA
{
public:
ProductA2();
~ProductA2();
protected:
private:
}; class ProductB1: public AbstractProductB{
public:
ProductB1();
~ProductB1();
protected:
private:
}; class ProductB2: public AbstractProductB{
public:
ProductB2();
~ProductB2();
protected:
private:
}; #endif
 //Product.cpp

 #include "Product.h"
#include <iostream> using namespace std; AbstractProductA::AbstractProductA() {
cout << "AbstractProductA..." << endl;
} AbstractProductA::~AbstractProductA() {
cout << "~AbstractProductA..." << endl;
} AbstractProductB::AbstractProductB() {
cout << "AbstractProductB..." << endl;
} AbstractProductB::~AbstractProductB() {
cout << "~AbstractProductB..." << endl;
} ProductA1::ProductA1() {
cout << "ProductA1..." << endl;
}
ProductA1::~ProductA1() {
cout << "~ProductA1..." << endl;
} ProductA2::ProductA2() {
cout << "ProductA2..." << endl;
}
ProductA2::~ProductA2() {
cout << "~ProductA2..." << endl;
} ProductB1::ProductB1() {
cout << "ProductB1..." << endl;
}
ProductB1::~ProductB1() {
cout << "~ProductB1..." << endl;
} ProductB2::ProductB2() {
cout << "ProductB2..." << endl;
}
ProductB2::~ProductB2() {
cout << "~ProductB2..." << endl;
}
 //AbstractFactory.h

 #ifndef ABSTRACTFACTORY_H
#define ABSTRACTFACTORY_H class AbstractProductA;
class AbstractProductB; class AbstractFactory{
public:
virtual ~AbstractFactory();
virtual AbstractProductA* CreateProductA() = ;
virtual AbstractProductB* CreateProductB() = ;
protected:
AbstractFactory();
private:
}; class ConcreteFactory1: public AbstractFactory{
public:
ConcreteFactory1();
~ConcreteFactory1();
AbstractProductA* CreateProductA();
AbstractProductB* CreateProductB();
protected:
private:
}; class ConcreteFactory2: public AbstractFactory{
public:
ConcreteFactory2();
~ConcreteFactory2();
AbstractProductA* CreateProductA();
AbstractProductB* CreateProductB();
protected:
private:
}; #endif
 //AbstractFactory.cpp

 #include "AbstractFactory.h"
#include "Product.h"
#include <iostream> using namespace std; AbstractFactory::AbstractFactory() {
cout << "AbstractFactory..." << endl;
} AbstractFactory::~AbstractFactory() {
cout << "~AbstractFactory..." << endl;
} ConcreteFactory1::ConcreteFactory1() {
cout << "ConcreteFactory1..." << endl;
} ConcreteFactory1::~ConcreteFactory1() {
cout << "~ConcreteFactory1..." << endl;
} AbstractProductA* ConcreteFactory1::CreateProductA() {
return new ProductA1();
}
AbstractProductB* ConcreteFactory1::CreateProductB() {
return new ProductB1();
} ConcreteFactory2::ConcreteFactory2() {
cout << "ConcreteFactory2..." << endl;
} ConcreteFactory2::~ConcreteFactory2() {
cout << "~ConcreteFactory2..." << endl;
} AbstractProductA* ConcreteFactory2::CreateProductA() {
return new ProductA2();
}
AbstractProductB* ConcreteFactory2::CreateProductB() {
return new ProductB2();
}
 //main.cpp

 #include"AbstractFactory.h"
#include<iostream> using namespace std; int main(int argc,char*argv[])
{
AbstractFactory* concretefactory1 = new ConcreteFactory1();
concretefactory1->CreateProductA();
concretefactory1->CreateProductB(); AbstractFactory* concretefactory2 = new ConcreteFactory2();
concretefactory2->CreateProductA();
concretefactory2->CreateProductB();
return ;
}

运行结果:

AbstractFactory...
ConcreteFactory1...
AbstractProductA...
ProductA1...
AbstractProductB...
ProductB1...
AbstractFactory...
ConcreteFactory2...
AbstractProductA...
ProductA2...
AbstractProductB...
ProductB2...
请按任意键继续. . .

c++设计模式系列----factory模式的更多相关文章

  1. 设计模式 - Abstract Factory模式(abstract factory pattern) 详细说明

    Abstract Factory模式(abstract factory pattern) 详细说明 本文地址: http://blog.csdn.net/caroline_wendy/article/ ...

  2. 设计模式之Factory模式(C++)

    Factory模式具有两大重要的功能: (1).定义创建对象的接口,封装了对象的创建: (2).使具体化类工作延迟到了子类中. //Product.h #ifndef _PRODUCT_H_ #def ...

  3. PHP设计模式系列 - 外观模式

    外观模式 通过在必需的逻辑和方法的集合前创建简单的外观接口,外观设计模式隐藏了调用对象的复杂性. 外观设计模式和建造者模式非常相似,建造者模式一般是简化对象的调用的复杂性,外观模式一般是简化含有很多逻 ...

  4. akka设计模式系列-While模式

    While模式严格来说是while循环在Akka中的合理实现.while是开发过程中经常用到的语句之一,也是绝大部分编程语言都支持的语法.但while语句是一个循环,如果循环条件没有达到会一直执行wh ...

  5. PHP设计模式系列 - 工厂模式

    工厂模式 提供获取某个对象实例的一个接口,同时使调用代码避免确定实例化基类的步骤. 工厂模式 实际上就是建立一个统一的类实例化的函数接口.统一调用,统一控制. 工厂模式是php项目开发中,最常用的设计 ...

  6. 设计模式之Factory模式 代码初见

    ObjectFactory就是通过Factory建造一个Object,比如说DBConnectionFactory就是专门建造DBConnection的工厂 BuilderFactory就是通过Fac ...

  7. PHP设计模式系列 - 委托模式

    委托模式 通过分配或委托其他对象,委托设计模式能够去除核心对象中的判决和复杂的功能性. 应用场景 设计了一个cd类,类中有mp3播放模式,和mp4播放模式 改进前,使用cd类的播放模式,需要在实例化的 ...

  8. c++设计模式系列----builder模式

    看了好几处关于builder模式的书和博客,总感觉不是很清楚,感觉不少书上的说的也不是很准确.最后还是看回圣经<设计模式>.看了好久终于感觉明白了一点了. 意图: builder模式提出的 ...

  9. akka设计模式系列-Chain模式

    链式调用在很多框架和系统中经常存在,算不得上是我自己总结的设计模式,此处只是简单介绍在Akka中的两种实现方式.我在这边博客中简化了链式调用的场景,简化后也更符合Akka的设计哲学. trait Ch ...

随机推荐

  1. 【bzoj1143】[CTSC2008]祭祀river Floyd+网络流最小割

    题目描述 在遥远的东方,有一个神秘的民族,自称Y族.他们世代居住在水面上,奉龙王为神.每逢重大庆典, Y族都会在水面上举办盛大的祭祀活动.我们可以把Y族居住地水系看成一个由岔口和河道组成的网络.每条河 ...

  2. Go语言【第五篇】:Go条件语句

    Go语言条件 条件语句需要开发者通过指定一个或多个条件,并通过测试条件是否为true来决定是否执行指定语句,并在条件为false的情况再执行另外的语句.下图展示了程序语言中条件语句的结构: Go语言提 ...

  3. Linux查看PCIe版本及速率

    Linux查看PCIe版本及速率 PCIE有四种不同的规格,通过下图来了解下PCIE的其中2种规格 查看主板上的PCI插槽 # dmidecode | grep --color "PCI&q ...

  4. 2018牛客多校第六场 G.Pikachu

    题意: 给出一棵n个点的树,每条边有边权.对这个树加边变成一个完全图.新加的边的权值为边上两点在树上的距离.求完全图上任意两点的最大流之和. 题解: 一共有C(n,2)个点对.假设当前求s到t之间的最 ...

  5. CF724E Goods transportation 最小割 DP

    照惯例CF的题不放原题链接... 题意:一个序列上有n个点,每个点有权值pi和si.表示这个点一开始有pi个物品,最多可以卖出si个物品,每个点都可以把物品向编号更大的点运输,但是对于i < j ...

  6. BZOJ1014:[JSOI2008]火星人prefix——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=1014 Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样 ...

  7. 《Java程序设计》第六周学习总结 20165218 2017-2018-1

    20165218 2017-2018-1 <Java程序设计>第六周学习总结 教材学习内容总结 第8章 常用实用类 String类 不可以有子类 在java.lang 包中,被默认引入 S ...

  8. 【BZOJ 3569】DZY Loves Chinese II 随机化+线性基

    用到一个结论——[先建树,再给每个非树边一个权值,每个树边的权值为覆盖他的非树边的权值的异或和,然后如果给出的边存在一个非空子集异或和为0则不连通,否则连通](必须保证每条边的出现和消失只能由自己产生 ...

  9. JavaScript如何获得input元素value的值

    在JavaScript中获取input元素value的值: 方法一: <!DOCTYPE html> <html> <head> <meta charset= ...

  10. some interesting words

    No one gets rich betting against the market. Never bet against the Fed. Bulls make money, bears make ...