问题描述

假设我们要开发一款游戏, 当然为了吸引更多的人玩, 游戏难度不能太大(让大家都没有信心了,估计游戏也就没有前途了),但是也不能太简单(没有挑战性也不符合玩家的心理)。于是我们就可以采用这样一种处理策略: 为游戏设立等级,初级、中级、高级甚至有BT 级。 假设也是过关的游戏, 每个关卡都有一些怪物( monster) 守着, 玩家要把这些怪物干掉才可以过关。 作为开发者, 我们就不得不创建怪物的类, 然后初级怪物、 中级怪物等都继承自怪物类(当然不同种类的则需要另创建类,但是模式相同)。在每个关卡, 我们都要创建怪物的实例,例如初级就创建初级怪物( 有很多种类)、中级创建中级怪物等。可以想象在这个系统中, 将会有成千上万的怪物实例要创建, 问题是还要保证创建的时候不会出错:初级不能创建 BT 级的怪物(玩家就郁闷了,玩家一郁闷,游戏也就挂挂了),反之也不可以。

AbstractFactory 模式就是用来解决这类问题的:要创建一组相关或者相互依赖的对象。

UML类图

其关键就是将这一组对象的创建封装到一个用于创建对象的类( ConcreteFactory)中, 维护这样一个创建类总比维护 n 多相关对象的创建过程要简单的多

适用场合

工厂方法模式适用于产品种类结构单一的场合,为一类产品提供创建的接口;而抽象工厂方法适用于产品种类结构多的场合,主要用于创建一组(有多个种类)相关的产品,为它们提供创建的接口;就是当具有多个抽象角色时,抽象工厂便可以派上用场。

代码实现

#include <iostream>
#include <string>
using namespace std; class IUser
{
public:
virtual void getUser() = 0;
virtual void setUser() = 0;
}; class SqlUser :public IUser
{
public:
void getUser()
{
cout << "在sql中返回user" << endl;
}
void setUser()
{
cout << "在sql中设置user" << endl;
}
}; class AccessUser :public IUser
{
public:
void getUser()
{
cout << "在Access中返回user" << endl;
}
void setUser()
{
cout << "在Access中设置user" << endl;
}
}; class IDepartment
{
public:
virtual void getDepartment() = 0;
virtual void setDepartment() = 0;
}; class SqlDepartment :public IDepartment
{
public:
void getDepartment()
{
cout << "在sql中返回Department" << endl;
}
void setDepartment()
{
cout << "在sql中设置Department" << endl;
}
}; class AccessDepartment :public IDepartment
{
public:
void getDepartment()
{
cout << "在Access中返回Department" << endl;
}
void setDepartment()
{
cout << "在Access中设置Department" << endl;
}
}; class IFactory
{
public:
virtual IUser *createUser() = 0;
virtual IDepartment *createDepartment() = 0;
}; class SqlFactory :public IFactory
{
public:
IUser *createUser()
{
return new SqlUser();
}
IDepartment *createDepartment()
{
return new SqlDepartment();
}
}; class AccessFactory :public IFactory
{
public:
IUser *createUser()
{
return new AccessUser();
}
IDepartment *createDepartment()
{
return new AccessDepartment();
}
}; /*************************************************************/ class DataAccess
{
private:
static string db;
//string db="access";
public:
static IUser *createUser()
{
if (db == "access")
{
return new AccessUser();
}
else if (db == "sql")
{
return new SqlUser();
}
}
static IDepartment *createDepartment()
{
if (db == "access")
{
return new AccessDepartment();
}
else if (db == "sql")
{
return new SqlDepartment();
}
}
};
string DataAccess::db = "sql"; /*************************************************************/ int main()
{
//IFactory *factory=new SqlFactory();
IFactory *factory;
IUser *user;
IDepartment *department; factory = new AccessFactory();
user = factory->createUser();
department = factory->createDepartment(); user->getUser();
user->setUser();
department->getDepartment();
department->setDepartment(); user = DataAccess::createUser();
department = DataAccess::createDepartment(); user->getUser();
user->setUser();
department->getDepartment();
department->setDepartment(); return 0;

运行结果:


抽象工厂模式的优缺点

优点:(1)易于切换产品系列,由于具体工厂类在一个应用中只需要在初始化的时候出现一次,使得改变具体工厂非常容易。(2)具体的创建实例过程与客户端分离,客户端通过他们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户端代码中。---充分运用了开放封闭原则和依赖倒转原则。

缺点:(2)根据上例,抽象工厂模式可以很方便地切换两个数据库访问的代码,但是如果你的需求来自增加功能,比如增加项目表Project,就至少需要增加三个雷,IProject、SqlserverProject、AccessProject,而且还要更改IFactory、SqlserverFactory和AccessFactory才行。

优化

(1)用简单工厂来改进抽象工厂

参考文献:

《C++设计模式》

《大话设计模式》

可推荐博客:C++设计模式——抽象工厂模式

c++实现反射

C++实现反射机制

 

设计模式之抽象工厂模式(附带类似反射功能的实现/c++)的更多相关文章

  1. 设计模式:抽象工厂模式(Abstract Factory)

    定   义:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类. 结构图: 示例结构图: 实体类: class User { public int Id { get; set; } p ...

  2. 乐在其中设计模式(C#) - 抽象工厂模式(Abstract Factory Pattern)

    原文:乐在其中设计模式(C#) - 抽象工厂模式(Abstract Factory Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 抽象工厂模式(Abstract Factor ...

  3. 桥接模式及C++实现 C++设计模式-AbstractFactory抽象工厂模式

    桥接模式及C++实现 桥接模式 先说说桥接模式的定义:将抽象化(Abstraction)与实现化(Implementation)分离,使得二者可以独立地变化. 桥接模式号称设计模式中最难理解的模式之一 ...

  4. Java 设计模式之抽象工厂模式(三)

    原文地址:Java 设计模式之抽象工厂模式(三) 博客地址:http://www.extlight.com 一.前言 上篇文章 <Java 设计模式之工厂模式(二)>,介绍了简单工厂模式和 ...

  5. 【设计模式】抽象工厂模式 Abstract Factory Pattern

    简单工厂模式是一个工厂类根据工厂方法的参数创建不出不同的产品, 工厂方法模式是每一个产品都有一个一一对应的工厂负责创建该产品.那么今天要讲的抽象工厂模式是一个工厂能够产生关联的一系列产品.抽象工厂模式 ...

  6. java设计模式之抽象工厂模式

    上一篇文章(http://www.cnblogs.com/liaoweipeng/p/5768197.html)讲了简单工厂模式,但是简单工厂模式存在一定的问题,如果想要拓展程序,必须对工厂类进行修改 ...

  7. php设计模式之抽象工厂模式

    之前总结了一下工厂模式,其实准确地说是简单 工厂模式,在它的基础上再进行抽象就可以得到一种新的模式:抽象工厂模式. 专业一点的定义为: 抽象工厂模式(Abstact Factory)是一种常见的软件设 ...

  8. (@WhiteTaken)设计模式学习——抽象工厂模式

    抽象工厂模式,可以向客户端提供一个接口,而客户端不用指定具体的类型创建对象,却能够创建多个产品族(一类具有共性产品,如地域等)的对象. 下面直接上代码. 1.苹果需要实现水果的接口,而苹果可以有北方的 ...

  9. 再起航,我的学习笔记之JavaScript设计模式06(抽象工厂模式)

    我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 前两 ...

随机推荐

  1. e 的由来

    https://www.zhihu.com/question/20296247 对数的发现 很多科学家发现对数螺线在自然界中广泛存在.从大如星系.台风,到小如花朵.海螺……宇宙中到处都是对数螺线的身影

  2. day12 Python字典

    类:dict #字典是无序的 1.前戏 info = { "k1": "v1", # 键值对 "k2": "v2" } ...

  3. LBS

  4. MyBatis+Hibernate+JDBC对比分析

    MyBatis目前作为持久层,用的最多,因为它符合互联网开发的变动性,实际开发中需求总会有这样的,那样的变动,MyBatis虽然没有Hibernate那么全自动化,而且对于开发人员的sql能力要求比较 ...

  5. QT listwiget 控件添加图片

    很多的时候我们需要制作类似手机的中的电子相框, 可以用listwidget 控件实现 直接上代码 MainWindow::MainWindow(QWidget *parent) : QMainWind ...

  6. MySQL(八)子查询和分组查询

    一.子查询 1.子查询(subquery):嵌套在其他查询中的查询. 例如:select user_id from usertable where mobile_no in (select mobil ...

  7. MySQL(七)联结表

    一.联结表基础知识 1.关系表 把信息分解成多个表,一类数据一个表,各表通过某些常用值(即关系设计中的关系(relational))互相关联: 2.外键(foreign key):外键为某个表中的一列 ...

  8. System.ServiceModel.CommunicationException: 接收HTTP 响应时错误发生

    具体错误信息例如以下: System.ServiceModel.CommunicationException: 接收对 http://110.110.110.110/TestService/TestS ...

  9. 重写Override ToString()方法

    使用一个小例子来演示: 创建一个普通类别: class Ax { private int _ID; public int ID { get { return _ID; } set { _ID = va ...

  10. Tensorflow实例:利用LSTM预测股票每日最高价(一)

    RNN与LSTM 这一部分主要涉及循环神经网络的理论,讲的可能会比较简略. 什么是RNN RNN全称循环神经网络(Recurrent Neural Networks),是用来处理序列数据的.在传统的神 ...