工厂与观察者模式

工厂模式介绍

通过一个加工厂,在这个工厂中添加对应材料,我们就可以得到想要的东西,在程序设计中,这种模式就叫做工厂模式,工厂生成出的产品就是某个类的实例,也就是对象。

关于工厂模式一共有三种,分别是:简单工厂模式、工厂模式、抽象工厂模式。

简单工厂模式

比如说你要生产一些物品,生产的方法都是一样的只是原材料不同。你可以设计一个基类,提供生产方法。然后将要生产的对象材料加入到生产类中即可。后面可以再定义一个对象工厂类,用来创建对应材料。

创建一个新的类, 可以将这个类称之为工厂类。对于简单工厂模式来说,需要的工厂类只有一个。工厂类中添加一个公共的成员函数,通过这个函数来创建我们需要的对象,通过这个对象调用工厂函数,这样就可以生产出一个指定类型的实例对象了。这里可以使用c++中的多态来完成。

例如:先定义一个基类,将其方法定义为虚函数。

class Product
{
public:Product(){;}virtual void produce(){cout << "进行生产" << endl;}virtual ~Product(){cout << "资源释放" << endl;}
};

定义要实例化的对象

class Milk :public Product
{
public:void produce(){cout << "生产了牛奶" << endl;}~Milk(){cout << "delete Milk" << endl;}
};class Apple :public Product
{
public:void product(){cout << "生产了apple" << endl;}~Apple(){cout << "delete apple" << endl;}
};

定义物品工厂类,用来生产对应材料

enum class Type :char { milk,apple };
class Factory
{
public:Product* p = nullptr;Product* create(Type T){switch (T){case Type::milk:p = new Milk;break;case Type::apple:p = new Apple;break;default:break;}return p;}
};
int main()
{Factory* f = new Factory;Product* p = f->create(Type::milk);//需要生产材料,就对其参数进行修改p->produce();delete p;return 0;
}

caf69a45a766483da2fc2a1fe83f8b3c.png

 工厂类模式

如果要可以生成更多种类的物品,需要添加更多的物品对象,同时还要在工厂函数的switch语句中添加更多的case,很明显这违背了封闭原则。

简单工厂模式是只有一个工厂类,而工厂模式是有很多的工厂类。

 

  1. 一个基类,包含一个虚工厂函数,用于实现多态。
  2. 多个子类,重写父类的工厂函数。每个子工厂类负责生产某种物品,这相当于再次解耦,如果要生产新物品,那么只需要添加对应的工厂类,无需修改原有的代码。

代码:

class Product
{
public:virtual void produce(){cout << "进行生产" << endl;}virtual ~Product(){cout << "资源释放" << endl;}
};class Milkpro :public Product
{
public:void produce(){cout << "生产了牛奶" << endl;}~Milkpro(){cout << "delete Milk" << endl;}
};class Applepro :public Product
{
public:void product(){cout << "生产了apple" << endl;}~Applepro(){cout << "delete apple" << endl;}
};class Factory//并没有在这个类中直接生产材料,而是定义为抽象类
{
public:virtual Product* creat() = 0;virtual ~Factory(){;}
};class Milk :public Factory
{
public:Product* creat(){return new Milkpro;}~Milk(){cout << "delete Milk" << endl;}
};
class Apple :public Factory
{
public:Product* creat(){return new Applepro;}~Apple(){cout << "delete Apple" << endl;}
};
int main()
{Factory* f = new Milk;Product* p= f->creat();p->produce();delete p;return 0;	
}

27ba17f099df42d884bec8c171e88f8f.png

 抽象工厂类

假如要生产一艘船,该的组成为:

船体,船的动力系统,船中配备的武器。

船体的选择:木材 合金

动力系统的选择:人力驱动,核反应驱动

武器的选择:枪,自动机关炮

这样一共就有8种选则。

船体,因为船体材料的这个属性是可变的,所以还需要给它提供一个抽象类,在这个抽象类的子类中就可以去更换不同的船体材料。

class ShipBody
{
public:virtual string getShipBody() = 0;virtual ~ShipBody() {}
};class WoodBody : public ShipBody
{
public:string getShipBody() override{return string("用<木材>制作轮船船体...");}
};class MetalBody : public ShipBody
{
public:string getShipBody() override{return string("用<合金>制作轮船船体...");}
};

动力系统与武器也是一样:

// 动力
class Engine
{
public:virtual string getEngine() = 0;virtual ~Engine() {}
};class Human : public Engine
{
public:string getEngine() override{return string("使用<人力驱动>...");}
};
class Nuclear : public Engine
{
public:string getEngine() override{return string("使用<核能驱动>...");}
};// 武器
class Weapon
{
public:virtual string getWeapon() = 0;virtual ~Weapon() {}
};class Gun : public Weapon
{
public:string getWeapon() override{return string("配备的武器是<枪>");}
};class Cannon : public Weapon
{
public:string getWeapon() override{return string("配备的武器是<自动机关炮>");}
};

一首船需要3个组成部分,这里用3个变量来表示:

class Ship
{
public:Ship(ShipBody* body, Weapon* weapon, Engine* engine) :m_body(body), m_weapon(weapon), m_engine(engine){}string getProperty(){
//      这也是多态实现,获取对应船组成部分的材料string info = m_body->getShipBody() + m_weapon->getWeapon() + m_engine->getEngine();return info;}~Ship(){delete m_body;delete m_engine;delete m_weapon;}
private:ShipBody* m_body = nullptr;Weapon* m_weapon = nullptr;Engine* m_engine = nullptr;
};

工厂类与上面一样,不直接进行提供船部件,而是定义为抽象类,让子类去提供船的部件。

/ 工厂类
class AbstractFactory
{
public:virtual Ship* createShip() = 0;virtual ~AbstractFactory() {}
};class BasicFactory : public AbstractFactory//定义木头,枪,人力的船
{
public:Ship* createShip() override{Ship* ship = new Ship(new WoodBody, new Gun, new Human);cout << "<基础型>战船生产完毕, 可以下水啦..." << endl;return ship;}
};

 结果:

int main()
{AbstractFactory* factroy = new BasicFactory;Ship* ship = factroy->createShip();cout << ship->getProperty();delete ship;delete factroy;return 0;
}

3a2868f99e6b4a99ba5b927555b4d37f.png

对比:

  • 简单工厂模式不能遵守开放-封闭原则,该工厂类没有设置为抽象类,要在该类中直接添加生产对象。
  • 工厂模式创建的对象  对应的类不需要提供抽象类,需要创建什么对象,直接提供对应的子类
  • 抽象工厂模式创建的对象  对应的类有抽象的基类,创建的对象有多种不同的组合方法。

观察者模式

一个简单的例子:交叉路口的红绿灯。过往的车辆就是观察者或则是订阅者,信号灯就是消息的发布者。当车辆到了该路口,车辆就会观测路灯,当路灯为红灯时,车辆即可通行。当车辆远离该路口时,车辆就不需要观察路灯的信号了。

其他例子:购买的商品被送到菜鸟驿站,会收到驿站发送的提示信息。

这里以报刊为例,报刊可以发布多种类型的消息给不同的人。

发布者,需要满足以下的需求:

  • 添加订阅者,将所有的订阅者存储起来
  • 删除订阅者,将其从订阅者列表中删除
  • 将消息发送给订阅者(发通知)

发布者

发布者未必是一种类型的,不同的发布者可以发布不同种类的消息。先创建出一个发布者的抽象类。

class Observer;//订阅者抽象类

class NewsAgency//发布者抽象类
{
public:
    void attach(Observer* ob)
    {
        m_list.push_back(ob);//增加订阅者
    }
    void deatch(Observer* ob)
    {
       m_list.remove(ob);//删除订阅者
    }
    virtual void notify(string msg) = 0;//通知
    virtual ~NewsAgency() {};
protected:
    list<Observer*> m_list;   // 订阅者列表
};

class News_A :public NewsAgency
{
public:
    void notify(string msg) override
    {
        cout << "这是NewA新闻报刊" << endl;
        for (auto ch : m_list)
        {
            ch->update(msg);
        }
    }
};
class News_B :public NewsAgency
{
public:
    void notify(string msg) override
    {
        cout << "这是NewB新闻报刊" << endl;
        for (auto ch : m_list)
        {
            ch->update(msg);
        }
    }
};

订阅者

观察者也未必只是一种对象,给所有的观察者定义一个抽象的基类。

// 抽象的订阅者类
class Observer
{
public:

  //通过构造函数给观察者类提供一个信息的发布者 
    Observer(string name, NewsAgency* news) :m_name(name), m_news(news) 
    {
        m_news->attach(this);//发布者对象将观察者对象存储了起来,可以收到发布的消息
    }
    void unsubscribe()
    {
        m_news->deatch(this);//订阅者取消订阅
    }
    virtual void update(string msg) = 0;
    virtual ~Observer() {}
protected:
    string m_name;
    NewsAgency* m_news;
};

class Observer_A : public Observer//订阅者A
{
public:
    using Observer::Observer;
    void update(string msg) override
    {
        cout << "订阅者A收到新消息: " << msg << endl;
    }
};

class Observer_B : public Observer//订阅者B
{
public:
    using Observer::Observer;
    void update(string msg) override
    {
        cout << "订阅者B收到新消息: " << msg << endl;
    }
};

过程

int main()
{News_A* New_a = new News_A;News_B* New_b = new News_B;Observer_A* obser_a = new Observer_A("observer_A",New_a);Observer_B* obser_b = new Observer_B("observer_B",New_b);New_a->notify("明天会下雨哦*************");New_b->notify("明天广场会进行发布会活动,请大家参加");return 0;
}

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/91799.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Qt::图层框架-图片图层-序列图层-QGraphicsPixmapItem

二维矢量动画智能制作软件开发合集 链接&#xff1a;软件开发技术分享及记录合集 个人开发二维矢量动画智能制作软件界面如下&#xff1a; 目录 一、图片序列图层原理 二、图片序列图层代码实现 三、图片序列图层软件测试视频 结束语 一、图片序列图层原理 本软件的11种…

C++11(列表初始化,声明,范围for)

目录 一、列表初始化 1、一般的列表初始化 2、容器的列表初始化 二、声明 1、 auto 2、decltype 3、nullptr 三、 范围for 一、列表初始化 1、一般的列表初始化 在C98中&#xff0c;标准允许使用花括号{}对数组或者结构体元素进行统一的列表初始值设定。 int main() {…

【OpenCV-Torch-dlib-ubuntu】Vm虚拟机linux环境摄像头调用方法与dilb模型探究

前言 随着金秋时节的来临&#xff0c;国庆和中秋的双重喜庆汇聚成一片温暖的节日氛围。在这个美好的时刻&#xff0c;我们有幸共同迎来一次长达8天的假期&#xff0c;为心灵充电&#xff0c;为身体放松&#xff0c;为未来充实自己。今年的国庆不仅仅是家国团聚的时刻&#xff…

scala基础入门

一、Scala安装 下载网址&#xff1a;Install | The Scala Programming Language ideal安装 &#xff08;1&#xff09;下载安装Scala plugins &#xff08;2&#xff09;统一JDK环境&#xff0c;统一为8 &#xff08;3&#xff09;加载Scala &#xff08;4&#xff09;创建工…

LabVIEW学习笔记五:错误,visa关闭超时(错误-1073807339)

写的串口调试工具&#xff0c;其中出现了这个错误 这是串口接收的部分&#xff0c;如果没有在很短的时间内收到外界发进来的数据&#xff0c;这里就会报错。 先在网上查了一下&#xff0c;这个问题很常见&#xff0c;我找到了官方的解答&#xff1a; VISA读取或写入时出现超时…

【JavaEE】CSS

CSS 文章目录 CSS语法引入方式内部样式表行内样式表外部样式 选择器基础选择器标签选择器类选择器id选择器通配符选择器 复合选择器后代选择器伪类选择器链接伪类选择器 字体设置设置文本颜色粗细样式文本对齐 背景背景颜色背景平铺背景尺寸 圆角矩形元素显示模式块级元素 盒模…

Pikachu靶场——XXE 漏洞

文章目录 1. XXE1.1 查看系统文件内容1.2 查看PHP源代码1.3 查看开放端口1.4 探测内网主机 1. XXE 漏洞描述 XXE&#xff08;XML External Entity&#xff09;攻击是一种利用XML解析器漏洞的攻击。在这种攻击中&#xff0c;攻击者通过在XML文件中插入恶意实体来触发解析器加载…

计算机图像处理-高斯滤波

高斯滤波 高斯滤波是一种线性平滑滤波&#xff0c;适用于消除高斯噪声&#xff0c;广泛应用于图像处理的减噪过程。通俗的讲&#xff0c;高斯滤波就是对整幅图像进行加权平均的过程&#xff0c;每一个像素点的值&#xff0c;都由其本身和邻域内的其他像素值经过加权平均后得到…

1340. 跳跃游戏 V;2039. 网络空闲的时刻;2767. 将字符串分割为最少的美丽子字符串

1340. 跳跃游戏 V 核心思想&#xff1a;动态规划记忆化搜索。定义dfs(i)&#xff0c;表示从i开始最多可以访问多少个下标&#xff0c;然后统计往左跳和往右边跳的最大值&#xff0c;思路其实比较简单&#xff0c;但是代码我感觉还是不太好想。 2039. 网络空闲的时刻 核心思想…

W5100S_EVB_PICO快速入门之MQTT篇(十二)

目录 1. 前言 2. MQTT介绍 2.1 什么是mqtt&#xff1f; 2.2 特点 2.3 应用场景 2.4 MQTT协议实现方式 3. 硬件及接线方式 3.1 硬件准备 3.2 硬件介绍 3.3 接线图 4. 测试 4.1 MQTT测试流程图 4.2 相关代码 4.3 测试现象 5. 相关链接&#xff1a; 1. 前言 随着物…

vue下载在前端存放的pdf文件

vue下载在前端存放的pdf文件 注意&#xff0c;这里要在public文件夹中新建文件夹存放静态资源&#xff0c;不能在src文件夹中新建文件夹存放静态资源&#xff0c;因为public文件夹中的文件资源不会被npm run build打包编译。大家打包一下&#xff0c;就会发现 模板.pdf文件 是存…

【C++入门指南】类和对象(上)

【C杂货店】类和对象&#xff08;上&#xff09; 一、面向过程和面向对象初步认识二、类的引入三、类的定义四、类的访问限定符及封装4.1 访问限定符4.2 封装 五、类的作用域六、类的实例化七、类对象模型7.1 类对象的存储规则7.2 例题7.3结构体内存对齐规则 八、this指针8.2 t…

第 114 场 LeetCode 双周赛题解

A 收集元素的最少操作次数 模拟: 反序遍历数组&#xff0c;用一个集合存当前遍历过的不超过 k k k 的正数 class Solution { public:int minOperations(vector<int> &nums, int k) {unordered_set<int> vis;int n nums.size();int i n - 1;for (;; i--) {if…

[Framework] Android Binder 工作原理

Binder 是 Android 系统中主要的 IPC 通信方式&#xff0c;其性能非常优异。但是包括我在内的很多开发者都对它望而却步&#xff0c;确实比较难&#xff0c;每次都是看了忘&#xff0c;忘了看&#xff0c;但是随着工作的时间约来越长&#xff0c;每次看也都对 Binder 有新的认识…

使用自功率谱、互功率谱估计滤波器幅频特性

这段时间终于对工程中的随机信号的一般处理方式有点头绪了&#xff0c;功率谱密度估计是十分重要的方式之一&#xff0c;仍需继续深入细化相关内容。 示例&#xff1a;使用自功率谱、互功率谱估计滤波器幅频特性&#xff0c;自己实现 & Matlab自带函数实现。 clc;clear;cl…

HTML之如何下载网页中的音频(二)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

毅速课堂:3D打印随形水路设计应注意什么?

随形水路是一种基于3D打印技术的新型模具冷却水路&#xff0c;能有效提高冷却效率、缩短冷却周期、提升产品良率、提高生产效率、 与传统的水路设计相比&#xff0c;随形水路更加贴合模具型腔表面&#xff0c;能够更加均匀地分配冷却水&#xff0c;使模具各部分的冷却效果得到有…

系统集成|第二十一章(笔记)

目录 第二十一章 知识产权与法律法规21.1 知识产权21.2 法律法规 上篇&#xff1a;第二十章、收尾管理 第二十一章 知识产权与法律法规 21.1 知识产权 概述&#xff1a;狭义的知识产权就是传统意义上的知识产权&#xff0c;包括著作权&#xff08;含邻接权&#xff09;&#x…

生产者、消费者问题

线程六个状态&#xff1a; public enum State {/*** 新生*/NEW,/*** 运行*/RUNNABLE,/***阻塞*/BLOCKED,/*** 等待*/WAITING,/*** 超时等待*/TIMED_WAITING,/**死亡**/TERMINATED;} synchronized和lock的区别 1、synchronized是关键字&#xff0c;lock是类 2、synchronized全自…

doT.js模板学习笔记

doT.js模板学习笔记 欢迎学习doT.js模板学习笔记doT.js模板是什么doT.js 主要优势在doT.js好处引入方式基本语法语法示例结尾 欢迎学习doT.js模板学习笔记 doT.js官方网站 本文章得示例源码 doT.js模板是什么 doT.js 是一个 JavaScript 模板框架&#xff0c;在 web 前端使用 d…