问题:

假设我们要开发一个游戏--打怪物,首先,游戏有分等级,假设有初级,中级两个个等级(就不用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. 【bzoj4500】矩阵 带权并查集

    题目描述 有一个n*m的矩阵,初始每个格子的权值都为0,可以对矩阵执行两种操作: 1. 选择一行, 该行每个格子的权值加1或减1. 2. 选择一列, 该列每个格子的权值加1或减1. 现在有K个限制,每 ...

  2. 【bzoj4278】[ONTAK2015]Tasowanie 贪心+后缀数组

    题目描述 给定两个数字串A和B,通过将A和B进行二路归并得到一个新的数字串T,请找到字典序最小的T. 输入 第一行包含一个正整数n(1<=n<=200000),表示A串的长度. 第二行包含 ...

  3. 最新发现:Object.defineProperty()让数组的length属性变成只读

    将属性添加到对象, 或修改现有属性的特性---MSDN的解释. 语法 object.defineProperty(object, propertyname, descriptor) object: 必 ...

  4. P1120 小木棍 [数据加强版](poj 1011)

    题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度. 给出每段小木棍的长度,编 ...

  5. hadoop 将HDFS上多个小文件合并到SequenceFile里

    背景:hdfs上的文件最好和hdfs的块大小的N倍.如果文件太小,浪费namnode的元数据存储空间以及内存,如果文件分块不合理也会影响mapreduce中map的效率. 本例中将小文件的文件名作为k ...

  6. BZOJ1834 [ZJOI2010]network 网络扩容 【最大流,费用流】

    1834: [ZJOI2010]network 网络扩容 Time Limit: 3 Sec  Memory Limit: 64 MB Submit: 3394  Solved: 1774 [Subm ...

  7. BZOJ3156: 防御准备 【斜率优化dp】

    3156: 防御准备 Time Limit: 10 Sec  Memory Limit: 512 MB Submit: 2207  Solved: 933 [Submit][Status][Discu ...

  8. sublime Text 块编辑方法

    比如我们要把SQL语句中的多表查询结果封装成pojo SQL: SELECT a.id, a.title, a.sell_point, a.price, a.image, b.`name` categ ...

  9. DOM基本代码一

    dom学习基本代码第一部分 <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> < ...

  10. sql service (case when then else end ..... group by)

    1. 原表: courseid coursename score ------------------------------------- 1 java 70 2 oracle 90 3 xml 4 ...