问题:

假设我们要开发一个游戏--打怪物,首先,游戏有分等级,假设有初级,中级两个个等级(就不用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. 【bzoj2502】清理雪道 有上下界最小流

    题目描述 滑雪场坐落在FJ省西北部的若干座山上. 从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道),弧的方向代表斜坡下降的方向. 你的团队负责每周定时清理雪道.你们拥有一架直升飞 ...

  2. sql批量更新关系型数据库

    更改gb_groupd里的chargingrulesname的值UPDATE   tb_group SET tb_group.chargingrulesname =tb_chargingrules.c ...

  3. Django+haystack实现全文搜索出现错误 ImportError: cannot import name signals

    原因是在你的settings.py或者其他地方使用了  "import haystack" 当我们使用django-haysatck库时,表面上会有haystack库,但实际上并不 ...

  4. Python虚拟环境virtualenv的使用

    virtualenv 是一个创建孤立的Python环境的工具.可以让你创建各自独立的.互不影响的Python开发环境. 使用pip安装即可 pip install virtualenv 查看是否安装成 ...

  5. HDU.3342 Legal or Not (拓扑排序 TopSort)

    HDU.3342 Legal or Not (拓扑排序 TopSort) 题意分析 裸的拓扑排序 根据是否成环来判断是否合法 详解请移步 算法学习 拓扑排序(TopSort) 代码总览 #includ ...

  6. HDOJ(HDU).2660 Accepted Necklace (DFS)

    HDOJ(HDU).2660 Accepted Necklace (DFS) 点我挑战题目 题意分析 给出一些石头,这些石头都有自身的价值和重量.现在要求从这些石头中选K个石头,求出重量不超过W的这些 ...

  7. BZOJ1898: [Zjoi2005]Swamp 沼泽鳄鱼(矩阵乘法)

    1898: [Zjoi2005]Swamp 沼泽鳄鱼 题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1898 Description 潘塔 ...

  8. 使用feign调用服务的时候注意的问题

    服务端 rest api @RequestMapping(value = "/phone") public ResponsePhone getPhone(@RequestParam ...

  9. RabbitMQ 作用

    1.RabbitMQ 作用 同步变异步 解耦 削峰 2.

  10. CMDB服务器管理系统【s5day88】:采集资产之整合插件

    以后导入配置文件不用去from conf而是导入from lib.config,因为在这可以导入global_settings和settings.py import sys import os imp ...