简单工厂模式(Simple Factory)

UML类图示法

矩形框三层:

  • 第一层:类的名称,若为抽象类,斜体显示
  • 第二层:类的特性,通常是字段和属性
  • 第三层:类的操作,通常是方法或行为
  • 符号:'+':public, '-':private,'#':protected

类与类,类与接口之间的关系

  • 继承:空心三角形+实线
  • 接口:空心三角形+虚线
  • 关联:实线箭头
  • 聚合:空心菱形+实线箭头
  • 合成(组合)关系:实心的菱形+实线箭头

简单工厂模式

概念

简单工厂模式(Simple Factory Pattern):又称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。在简单工厂模式中,可以根据参数的不同返回不同类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。

模式结构

主要用于创建对象。新添加类时,不会影响以前的系统代码。核心思想是用一个工厂来根据输入的条件产生不同的类,然后根据不同类的 virtual 函数得到不同的结果。

工厂角色(Creator) 是简单工厂模式的核心,它负责实现创建所有具体产品类的实例。工厂类可以被外界直接调用,创建所需的产品对象。
抽象产品角色(Product) 是所有具体产品角色的父类,它负责描述所有实例所共有的公共接口。
具体产品角色(Concrete Product) 继承自抽象产品角色,一般为多个,是简单工厂模式的创建目标。工厂类返回的都是该角色的某一具体产品。

模式实例与解析(1)

考虑一个简单的应用场景,一个计算器可以提供多个不同的运算符(如加法、减法、乘法、除法等),这些运算符都源自同一个基类,不过在继承基类后不同的子类修改了部分属性从而使得它们可以呈现不同的外观,如果我们希望在使用这些运算符时,不需要创建这些子类,只需要知道我要做的是加法还是减法,并把符号传入方法即可返回一个结果,此时,就可以使用简单工厂模式。

注:所有用例只为体现设计模式思想,不考虑边界情况,如不考虑除数为0异常等。

#include <iostream>using namespace std;class Operation{
public:virtual double GetResult() = 0;double GetNumA() { return _numA; }double GetNumB() { return _numB; }void SetNum(double a, double b){_numA = a;_numB = b;}virtual ~Operation() = default;
private:double _numA = 0;double _numB = 0;
};class OperationAdd : public Operation
{
public:virtual double GetResult(){double res = 0;res = GetNumA() + GetNumB();return res;}
};class OperationSub : public Operation
{
public:virtual double GetResult(){double res = 0;res = GetNumA() - GetNumB();return res;}
};class OperationMul : public Operation
{
public:virtual double GetResult(){double res = 0;res = GetNumA() * GetNumB();return res;}
};class OperationDiv : public Operation
{
public:virtual double GetResult(){double res = 0;res = GetNumA() / GetNumB();return res;}
};class CalculatorFactory
{
public:static Operation* Create(char c){Operation *oper;switch(c){case '+':oper = new OperationAdd();break;case '-':oper = new OperationSub();break;case '*':oper = new OperationMul();break;case '/':oper = new OperationDiv();break;default:oper = new OperationAdd();break;}return oper;}
};int main()
{int a, b;cin >> a >> b;Operation * op = CalculatorFactory::Create('+');op->SetNum(a, b);double result = op->GetResult();cout << "result = " << result << endl;
}

从此以后,如果要加入新的运算符,只需要在新增子类并且在工厂类中的添加相应符号。

模式实例与解析(2)

再考虑一个简单的应用场景,某商店定期有促销活动,有满300返100,打八折,打五折,满200返50,等等,这些优惠都源自同一个基类,这也可以用工厂模式。

#include <iostream>
#include <string>
#include <unordered_map>using namespace std;unordered_map<string, int> mp{{"正常收费", 0}, {"满300返100", 1}, {"打八折", 2}};class CashSuper
{
public:virtual double accpetCash(double money) = 0;
};class CashNormal : public CashSuper
{
public:virtual double accpetCash(double money){ return money; }
};class CashRebate : public CashSuper
{
public:CashRebate(double moneyRebate):_moneyRebate(moneyRebate){}virtual double accpetCash(double money) { return money * _moneyRebate; }
private:double _moneyRebate = 0.9;
};class CashReturn : public CashSuper
{
public:CashReturn(double moneyCondition, double moneyReturn):_moneyCondition(moneyCondition), _moneyReturn(moneyReturn){}double accpetCash(double money){double result = money;if(money >= _moneyCondition){result = money - (money / _moneyCondition) * _moneyReturn; }return result;}
private:double _moneyCondition = 0.0;double _moneyReturn = 0.0;
};class CashFactory
{
public:static CashSuper* createCashAccept(string type){int StringValue = mp[type];CashSuper * cs = nullptr;switch(StringValue){case 0:cs = new CashNormal();break;case 1:cs = new CashReturn(300, 100);break;case 2:cs = new CashRebate(0.8);break;}return cs;}
};int main()
{double total = 0.0;string super;cin >> super;CashSuper *p = CashFactory::createCashAccept(super);total = p->accpetCash(300);cout << "total = " << total << endl;return 0;
}

因为C++中switch(expression)中的expression不支持string类表达式,所以为实现功能这里额外调用了unordered_map来匹配字符串。


工厂类中的方法必须是static方法,于是可以通过类名访问,也可以通过类的实例访问。而普通方法又叫实例方法,只能通过类的实例访问。当你需要什么,只需要传入一个正确的参数,就可以获取你所要的的对象,而无需知道其创建的细节。如果不用static反而违背了设计模式的初衷!

优缺点

优点:实现对象的创建和对象的使用分离,将对象的创建交给专门的工厂类负责
缺点:工厂类不够灵活,增加新的具体产品需要修改工厂类的判断逻辑代码,而且产品较多时,工厂方法代码将会非常复杂。

参考:

  1. 《大话设计模式》 程杰

  2. https://www.cnblogs.com/Bobby0322/p/4178412.html
  3. http://ruby-java.javaeye.com/blog/169854

转载于:https://www.cnblogs.com/Mered1th/p/10976346.html

简单工厂模式(Simple Factory)相关推荐

  1. Java设计模式之简单工厂模式(Simple Factory)

    [Java与模式]简单工厂模式(Simple Factory---吴义) 首先说明,Java与模式一系列的文章均是参考阎宏博士的<Java与模式>一书,加上自身的一些体会的探索,产生如下文 ...

  2. Net设计模式之简单工厂模式(Simple Factory Pattern)

    一.简单工厂模式简介(Bref Introduction)        简单工厂模式(Simple Factory Pattern)的优点是,工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实 ...

  3. 简单工厂模式-Simple Factory Pattern 工厂三兄弟之简单工厂模式(四):图表库解决方案的改进,简单工厂模式的简化,简单工厂模式总结

    4 方案的改进 Sunny软件公司开发人员发现在创建具体Chart对象时,每更换一个Chart对象都需要修改客户端代码中静态工厂方法的参数,客户端代码将要重新编译,这对于客户端而言,违反了" ...

  4. 设计模式的征途—2.简单工厂(Simple Factory)模式

    工厂模式是最常用的一种创建型模式,通常所说的工厂模式一般是指工厂方法模式.本篇是是工厂方法模式的"小弟",我们可以将其理解为工厂方法模式的预备知识,它不属于GoF 23种设计模式, ...

  5. 简单工厂(Simple Factory)模式

    简单工厂(Simple Factory)模式 Simple Factory模式根据提供给它的数据,返回几个可能类中的一个类的实例.通常它返回的类都有一个公共的父类和公共的方法. Simple Fact ...

  6. 设计模式(2)——创建型——工厂相关:简单工厂(Simple factory),工厂方法(Factory method),抽象工厂(Abstract factory)

    概要 这里试图描述23个设计模式中的两个工厂(Factory)相关的设计模式:工厂方法(Factorymethod),抽象工厂(Abstract factory). 注意点: 这两个都属于创建型设计模 ...

  7. PHP框架中的设计模式-工厂模式(简单工厂)|Simple Factory Pattern-ThinkPHP v3.2

    一. ThinkPHP简单工厂模式应用~之~根据数据库连接配置参数设定相应的数据库驱动类? 比如说当数据库类型'DB_TYPE'配置为'mysql',则ThinkPHP会自动建立MySQL的数据库连接 ...

  8. 设计模式之简单工厂模式(Simply Factory)摘录

    从设计模式的类型上来说,简单工厂模式是属于创建型模式,又叫静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一.简单工厂模式是由一个工厂对象决定创建出哪一种 ...

  9. c++设计模式之简单工厂模式

    模拟场景 要求使用简单工厂模式设计一个可以创建不同几何形状(如矩形.圆形.三角形)的绘图工具,每个几何图形都具有绘制Draw()和擦除Erase()两个方法: UML类图 分析需求: 首先这个绘图工具 ...

最新文章

  1. MySQL的btree索引和hash索引的区别
  2. 如何加快HTML页面加载速度
  3. CentOS下挂载iso文件
  4. linux主机基本情况,查看linux主机系统基本信息.pdf
  5. linux共享文件系统sy,Linux使用Samba实现文件共享
  6. JAVA 雪花算法 唯一ID生成工具类
  7. C++设计模式-桥接模式
  8. java 静态代码块 作用域_java static关键字和代码块
  9. Qt多线程-QThread
  10. kotlin null_Kotlin Null安全– Kotlin可空
  11. 云计算:大数据时代的系统工程(三)
  12. JavaScript: The Good Parts 学习随笔(三)
  13. paip.输入法编程---输入法ATIaN历史记录 v8b
  14. uipath数据爬取(结构化数据)
  15. BAT等大厂年薪30W+面试清单:JVM\MySQL\设计模式\分布式\微服务
  16. 抖音怎么投放广告,抖音广告投放效果
  17. 游戏测试成长之路02-测试用例
  18. 前端找实习岗的7条建议
  19. 山石网科面经(附参考回答)
  20. Ubuntu 设置屏幕字体大小

热门文章

  1. mysql 多表查询 优化_Mysql 多表联合查询效率分析及优化
  2. python import 文件路径_python之import子目录文件
  3. java await signal_java Condtion await方法和signal方法解析
  4. element走马灯自动_Element Carousel 走马灯的具体实现
  5. 基于python的系统构建_利用python构建一个简单的推荐系统
  6. linux ls使用方法,Linux/Ubuntu ls命令详解使用格式和方法
  7. imx6 休眠 功耗 电流_无线物联网和可穿戴设备的低功耗电源测量挑战
  8. 【流媒体服务器的搭建】1. 源码编译安装x264
  9. 什么叫预判_什么才是真正的用户画像?
  10. python快速入门课堂笔记_Python 快速入门笔记(10):文件及目录操作