问题:

假设我们要开发一个游戏--打怪物,首先,游戏有分等级,假设有初级,中级两个个等级(就不用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. 当要将其他类型转成String类型时候 看String的方法

    当要将其他类型转成String类型时候 看String的方法进行转换

  2. linux文件服务器:samba服务器

    windows上,需要和linux虚拟机进行方便的文件交互,总结一下遇到的问题. 1.samba简介 windows和windows之间共享文件可以用“网上邻居”,linux和linux间共享文件用 ...

  3. (四)Redis哈希表Hash操作

    Hash全部命令如下: hset key field value # 将哈希表key中的字段field的值设为value hget key field # 返回哈希表key中的字段field的值val ...

  4. bzoj 1797: [Ahoi2009]Mincut 最小割 (网络流)

    太神了直接看了hzwer的题解,有个新认识,一条路径上满流的一定是这条路径上所有边的最小值. type arr=record toward,next,cap,from:longint; end; co ...

  5. HDU3652:B-number——题解

    http://acm.hdu.edu.cn/showproblem.php?pid=3652 题目大意:给一个数n,求1-n所有满足下列条件的数的个数: 1.包含一个子串为“13” 2.能被13整除. ...

  6. Linux之SSL安全套接字20160704

    使用SSL前,先有 基本的TCP套接字连接.见demo代码 SSL_library_init();//在使用OpenSSL 之前,必须进行相应的协议初始化工作 OpenSSL_add_all_algo ...

  7. java使用POI操作XWPFDocument中的XWPFParagraph(段落)对象的属性略解

    我用的是office word 2016版 创建文本对象 XWPFDocument docxDocument = new XWPFDocument(); 创建段落对象 XWPFParagraph pa ...

  8. 蓝桥杯 最短路 spfa

    问题描述 给定一个n个顶点,m条边的有向图(其中某些边权可能为负,但保证没有负环).请你计算从1号点到其他点的最短路(顶点从1到n编号). 输入格式 第一行两个整数n, m. 接下来的m行,每行有三个 ...

  9. GYM 101875 2018 USP-ICMC

    3月自训 (1):10/12 A: 题意:每个人可以连边,最远连到第(i+k)%n个人,边权为这个人与另一个人连边距离,求生成一颗最大生成树的权值和是多少 题解:可以证明的是,我们每一个人都向接下来的 ...

  10. centos7下使用yum安装redis

    centos7下使用yum安装Redis 第一步:安装 yum –y install redis 第二步:启动 systemctl start redis.service 第三步:设置开机启动 sys ...