热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

设计模式之工厂模式(C++)

作者:翟天保Steven版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处一、工厂模式是什么&#x

作者:翟天保Steven
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处

一、工厂模式是什么?

       工厂模式是一种创建型的软件设计模式。定义一个用于创建对象的工厂接口,并让工厂子类决定实例化哪一个产品类,使产品类的实例化延迟到工厂子类中执行。说白了就是用来造东西的,一般是比较简单的东西,我们不需要知道它如何生产的,直接从工厂拿到产品即可。

       工厂模式的优点:

  1. 良好的封装性。将产品的实例化封装执行,避免被修改,这样的产品具备良好的一致性。
  2. 良好的扩展性。增加产品时,同步增加一个工厂子类,不会违反开闭原则。
  3. 标准的解耦合框架。使用者只需要知道自己要什么产品即可,不用去管产品具体的特性等等,降低了模块间的耦合。

      工厂模式的缺点:

  1. 代码量大。每加一个产品,都要加一个工厂子类,代码会显得臃肿。
  2. 不利于扩展复杂的产品结构。如果你要苹果、香蕉、梨,工厂模式的结构还可以,但如果你要山东的苹果、海南的香蕉、北京的苹果,就显得结构呆呆的。这可以用抽象工厂模式解决,对产品族和产品种类进行区分。

二、简单工厂模式

       在介绍工厂模式前,先介绍其前身-简单工厂模式,简单工厂模式是用一个简单的工厂类,直接对产品进行实例化,虽然大大减少了代码量,但是违反了设计中的开闭原则,因为每次添加产品,工厂类都要进行修改。

2.1 结构图

       客户端即Main主函数,调用简单工厂制造产品,并获取产品。具体要什么产品由客户端命令决定。

 2.2 代码示例

       场景描述:我联系了一个生产水果的工厂,从工厂拿了一个苹果、一个香蕉和一个梨,用来果腹,工厂给我一个报价我付钱即可。

//Prodect.h
/****************************************************/
#pragma once
#include
using namespace std;
// 产品种类
enum PRODECT_TYPE
{
APPLE, // 苹果
BANANA, // 香蕉
PEAR // 梨
};
// 抽象产品类
class Prodect
{
public:
// 构造函数
Prodect(int price) :m_price(price) {};
// 析构函数
virtual ~Prodect() {};
// 获取价格
int getPrice() {
return m_price;
}
protected:
// 产品价格
int m_price;
};
// 具体产品类-苹果
class AppleProdect : public Prodect
{
public:
// 构造函数
AppleProdect(int price) :Prodect(price) {
cout <<"获得了一个苹果。" < };
// 析构函数
virtual ~AppleProdect() {
cout <<"吃掉了一个苹果。" < };
};
// 具体产品类-香蕉
class BananaProdect : public Prodect
{
public:
// 构造函数
BananaProdect(int price) :Prodect(price) {
cout <<"获得了一个香蕉。" < };
// 析构函数
virtual ~BananaProdect() {
cout <<"吃掉了一个香蕉。" < };
};
// 具体产品类-梨
class PearProdect : public Prodect
{
public:
// 构造函数
PearProdect(int price) :Prodect(price) {
cout <<"获得了一个梨。" < };
// 析构函数
virtual ~PearProdect() {
cout <<"吃掉了一个梨。" < };
};

//Factory.h
/****************************************************/
#pragma once
#include
#include "Prodect.h"
using namespace std;
// 简单工厂
class SimpleFactory
{
public:
// 获取产品
Prodect* getProdect(PRODECT_TYPE type) {
Prodect* prodect &#61; nullptr;
switch (type)
{
case APPLE:
prodect &#61; new AppleProdect(5);
break;
case BANANA:
prodect &#61; new BananaProdect(2);
break;
case PEAR:
prodect &#61; new PearProdect(3);
break;
default:
cout <<"无该产品。" < break;
}
return prodect;
}
};

//main.cpp
/****************************************************/
#include
#include "Factory.h"
#include "Prodect.h"
using namespace std;
int main()
{
SimpleFactory* factory &#61; new SimpleFactory();
cout <<"开始生产。" < Prodect *A &#61; factory->getProdect(APPLE);
Prodect *B &#61; factory->getProdect(BANANA);
Prodect *C &#61; factory->getProdect(PEAR);
int applePrice &#61; A->getPrice();
int bananaPrice &#61; B->getPrice();
int pearPrice &#61; C->getPrice();
int sum &#61; A->getPrice() &#43; B->getPrice() &#43; C->getPrice();
cout <<"苹果价格&#xff1a;" < cout <<"香蕉价格&#xff1a;" < cout <<"梨子价格&#xff1a;" < cout <<"累计消费&#xff1a;" < delete A;
delete B;
delete C;
cout <<"享用完毕。" < return 0;
}

       程序结果如下。

        在上述示例中&#xff0c;我们可以看到&#xff0c;如果我想给工厂再添加一个产品&#xff0c;那么除了添加一个产品子类外&#xff0c;还要跑到简单工厂的类中进行switch的扩展&#xff0c;这样不利于代码的封装&#xff0c;破坏了开闭原则。而工厂模式的设计能弥补该不足。


三、工厂模式

3.1 结构图

       客户端即Main主函数&#xff0c;通过工厂子类来制造对应的产品&#xff0c;并获取产品。具体要什么产品由工厂子类决定。

 3.2 代码示例

       场景描述&#xff1a;我联系了一个生产水果的工厂&#xff0c;从工厂拿了一个苹果、一个香蕉和一个梨&#xff0c;用来果腹&#xff0c;工厂给我一个报价我付钱即可。

//Prodect.h
/****************************************************/
#pragma once
#include
using namespace std;
// 抽象产品类
class Prodect
{
public:
// 构造函数
Prodect(int price) :m_price(price) {};
// 析构函数
virtual ~Prodect() {};
// 获取价格
int getPrice() {
return m_price;
}
protected:
// 产品价格
int m_price;
};
// 具体产品类-苹果
class AppleProdect : public Prodect
{
public:
// 构造函数
AppleProdect(int price) :Prodect(price) {
cout <<"获得了一个苹果。" < };
// 析构函数
virtual ~AppleProdect() {
cout <<"吃掉了一个苹果。" < };
};
// 具体产品类-香蕉
class BananaProdect : public Prodect
{
public:
// 构造函数
BananaProdect(int price) :Prodect(price) {
cout <<"获得了一个香蕉。" < };
// 析构函数
virtual ~BananaProdect() {
cout <<"吃掉了一个香蕉。" < };
};
// 具体产品类-梨
class PearProdect : public Prodect
{
public:
// 构造函数
PearProdect(int price) :Prodect(price) {
cout <<"获得了一个梨。" < };
// 析构函数
virtual ~PearProdect() {
cout <<"吃掉了一个梨。" < };
};

//Factory.h
/****************************************************/
#pragma once
#include
#include "Prodect.h"
using namespace std;
// 抽象工厂类
class Factory
{
public:
// 获取产品
virtual Prodect* getProdect() &#61; 0;
};
// 具体工厂类-苹果
class AppleFactory : public Factory
{
public:
// 获取产品
virtual Prodect* getProdect() {
Prodect* prodect &#61; new AppleProdect(5);
return prodect;
}
};
// 具体工厂类-香蕉
class BananaFactory : public Factory
{
public:
// 获取产品
virtual Prodect* getProdect() {
Prodect* prodect &#61; new BananaProdect(2);
return prodect;
}
};
// 具体工厂类-梨
class PearFactory : public Factory
{
public:
// 获取产品
virtual Prodect* getProdect() {
Prodect* prodect &#61; new PearProdect(3);
return prodect;
}
};

//main.cpp
/****************************************************/
#include
#include "Factory.h"
#include "Prodect.h"
using namespace std;
int main()
{
Factory* factoryA &#61; new AppleFactory();
Factory* factoryB &#61; new BananaFactory();
Factory* factoryC &#61; new PearFactory();
cout <<"开始生产。" < Prodect *A &#61; factoryA->getProdect();
Prodect *B &#61; factoryB->getProdect();
Prodect *C &#61; factoryC->getProdect();
int applePrice &#61; A->getPrice();
int bananaPrice &#61; B->getPrice();
int pearPrice &#61; C->getPrice();
int sum &#61; A->getPrice() &#43; B->getPrice() &#43; C->getPrice();
cout <<"苹果价格&#xff1a;" < cout <<"香蕉价格&#xff1a;" < cout <<"梨子价格&#xff1a;" < cout <<"累计消费&#xff1a;" < delete A;
delete B;
delete C;
cout <<"享用完毕。" < return 0;
}

       程序结果如下。

        这样设计的好处就是如果多一个产品&#xff0c;那就只需要在产品类和工厂类中各扩展一个子类即可&#xff0c;不影响原有的程序。


四、总结

       我尽可能用较通俗的话语和直观的代码例程&#xff0c;来表述我对工厂模式的理解&#xff0c;或许有考虑不周到的地方&#xff0c;如果你有不同看法欢迎评论区交流&#xff01;希望我举的例子能帮助你更好地理解工厂模式。

       如果文章帮助到你了&#xff0c;可以点个赞让我知道&#xff0c;我会很快乐~加油&#xff01;


推荐阅读
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • 本文介绍了一个Java猜拳小游戏的代码,通过使用Scanner类获取用户输入的拳的数字,并随机生成计算机的拳,然后判断胜负。该游戏可以选择剪刀、石头、布三种拳,通过比较两者的拳来决定胜负。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 本文介绍了C++中省略号类型和参数个数不确定函数参数的使用方法,并提供了一个范例。通过宏定义的方式,可以方便地处理不定参数的情况。文章中给出了具体的代码实现,并对代码进行了解释和说明。这对于需要处理不定参数的情况的程序员来说,是一个很有用的参考资料。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 本文介绍了一种划分和计数油田地块的方法。根据给定的条件,通过遍历和DFS算法,将符合条件的地块标记为不符合条件的地块,并进行计数。同时,还介绍了如何判断点是否在给定范围内的方法。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • 本文介绍了解决二叉树层序创建问题的方法。通过使用队列结构体和二叉树结构体,实现了入队和出队操作,并提供了判断队列是否为空的函数。详细介绍了解决该问题的步骤和流程。 ... [详细]
  • 本文介绍了一个程序,可以输出1000内能被3整除且个位数为6的所有整数。程序使用了循环和条件判断语句来筛选符合条件的整数,并将其输出。 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
author-avatar
俊铭心怡雅琪
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有