23设计模式—工厂方法

news2025/1/17 0:27:07

文章目录

    • 0、模式类型
    • 1、Factory Method
      • 1.1、动机
      • 1.2、实现
    • 2、模式定义
    • 3、结构
    • 4、总结

0、模式类型

"对象创建"模式

  • 通过“对象创建”模式绕开new,来避免对象创建(new)过程中导致的紧耦合(依赖具体类),从而支持对象创建的稳定。他是接口抽象之后的第一步工作。

典型模式

  • Factory Method
  • Abstract Factory
  • Prototype
  • Builder

1、Factory Method

1.1、动机

  • 在软件系统中,经常面临着创建对象的工作;由于需求的变化,需要创建的对象的具体类型经常变化。
  • 如何应对这种变化?如何绕过常规的对象创建方法(new),提供一种“封装机制”来避免客户程序和这种“具体对象创建工作”的紧耦合?

1.2、实现

需求:假设现在有一个按钮,按钮点击一次产生某种文件分割的效果,现在是只有二进制文件分割的功能,以后需求可能会发生变化,可能会要有视频分割效果。

  1. 初始解决方案
class BinarySlice{
public:
    void Slice()
    {
        std::cout << "---BinarySlice---" << std::endl;
    }
};
#ifndef DESIGN_PATTERN_MAIN_BUTTON_H
#define DESIGN_PATTERN_MAIN_BUTTON_H
#include<iostream>
#include"Slice.h"
class MainButton{
public:
    void Button()
    {
        BinarySlice* slice = new BinarySlice();
        slice->Slice();
    }
};

#endif //DESIGN_PATTERN_MAIN_BUTTON_H

//
// Created by long on 2023/8/16.
//
#include<iostream>
#include"Main_button.h"
using namespace std;

int main()
{

    MainButton* button = new MainButton(); // 11,12行会依赖其他的类
    button->Button();

    return 0;
}

运行结果:
image.png
总结:这种解决方案的问题是会依赖MainButton类,以后如果需求变化需要修改代码。所以需要进行改进,让其能够应对未来的变化。
解决方案:我们在写代码的时候有一个原则,可以通过创造基类的方式来应对变化

  1. 添加基类的方法
//
// Created by long on 2023/9/1.
//

#ifndef MY_TEST_SLICE_H
#define MY_TEST_SLICE_H
#include<iostream>
class ISlice{
public:
    virtual void Slice() = 0;
    virtual ~ISlice(){}
};

class BinarySlice: public ISlice{
public:
    void Slice()
    {
        std::cout << "---BinarySlice---" << std::endl;
    }
};

class VideoSlice: public ISlice{
public:
    void Splitter()
    {
        std::cout << "---VideoSSlice---" << std::endl;
    }
};

class PictureSlice: public ISlice{
public:
    void Slice()
    {
        std::cout << "---PictureSlice---" << std::endl;
    }
};
#endif //MY_TEST_SLICE_H

//
// Created by long on 2023/9/1.
//

#ifndef DESIGN_PATTERN_MAIN_BUTTON_H
#define DESIGN_PATTERN_MAIN_BUTTON_H
#include<iostream>
#include"Slice.h"
class MainButton{
public:
    void Button()
    {
//        BinarySlice* slice = new BinarySlice();
        ISlice* slice = new BinarySlice(); //等号左边使用基类,可以应对变化,比较稳定,但是右边不稳定。
        slice->Slice();
    }
};

#endif //DESIGN_PATTERN_MAIN_BUTTON_H

//
// Created by long on 2023/8/16.
//
#include<iostream>
#include"Main_button.h"
using namespace std;

int main()
{

    MainButton* button = new MainButton();
    button->Button();
    return 0;
}

运行结果:
image.png
总结:虽然Main_button左边能够应对变化,但是右边如果未来需求变化,还是需要修改代码。
解决方案:通过虚函数的手段让其从编译期的初始化变成运行时的初始化。

  1. 最终解决方案(工厂方法)

代码:

//
// Created by long on 2023/9/1.
//

#ifndef MY_TEST_SLICE_H
#define MY_TEST_SLICE_H
#include<iostream>
class ISlice{
public:
    virtual void Slice() = 0;
    virtual ~ISlice(){}
};

class BinarySlice: public ISlice{
public:
    void Slice()
    {
        std::cout << "---BinarySlice---" << std::endl;
    }
};

class VideoSlice: public ISlice{
public:
    void Slice()
    {
        std::cout << "---VideoSlice---" << std::endl;
    }
};

class PictureSlice: public ISlice{
public:
    void Slice()
    {
        std::cout << "---PictureSlice---" << std::endl;
    }
};
#endif //MY_TEST_SLICE_H

//
// Created by long on 2023/9/1.
//

#ifndef DESIGN_PATTERN_SLICE_FACTORY_H
#define DESIGN_PATTERN_SLICE_FACTORY_H
#include<iostream>
#include"Slice.h"

class Slice_Factory{
public:
virtual ISlice* Factory() = 0;
virtual ~Slice_Factory(){}
};

class VideoSlice_Factory: public Slice_Factory{
public:
ISlice* Factory() override
{
    return new VideoSlice();
}
};

class BinarySlice_Factory: public Slice_Factory{
public:
ISlice* Factory() override
{
    return new BinarySlice();
}
};

class PictureSlice_Factory:  public Slice_Factory{
public:
ISlice* Factory() override
{
    return new PictureSlice();
}
};



#endif //DESIGN_PATTERN_SLICE_FACTORY_H
//
// Created by long on 2023/9/1.
//

#ifndef DESIGN_PATTERN_MAIN_BUTTON_H
#define DESIGN_PATTERN_MAIN_BUTTON_H
#include<iostream>
#include"Slice.h"
#include"Slice_Factory.h"
class MainButton{
public:
MainButton(Slice_Factory* factory)
{
    this->factory = factory;
}

void Button()
{
    //        BinarySlice* slice = new BinarySlice(); //1
    //        ISlice* slice = new BinarySlice(); //2等号左边使用基类,可以应对变化,比较稳定,但是右边不稳定。
    //        slice->Slice();
    ISlice* slice = factory->Factory(); // 通过传参将MainButton内部变为稳定,而不稳定的部分被赶出类外了。
    slice->Slice();
}

private:
Slice_Factory* factory;
};

#endif //DESIGN_PATTERN_MAIN_BUTTON_H
//
// Created by long on 2023/8/16.
//
#include<iostream>
#include"Main_button.h"
using namespace std;

int main()
{

    MainButton* button = new MainButton(new BinarySlice_Factory());
    button->Button();
    MainButton* button2 = new MainButton(new PictureSlice_Factory());
    button2->Button();

    return 0;
}

运行结果:
image.png

2、模式定义

定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使得一个类的实例化延迟(目的:解释,手段:虚函数)到子类。 ——《设计模式》GoF.

3、结构

image.png

4、总结

image.png

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

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

相关文章

多线程讲解(详解)

目录 什么是多线程&#xff1f; 为什么要使用多线程&#xff1f; 线程的创建 使用Thread实现 从以上代码我们梳理一下多线程创建步骤&#xff1a; 注意&#xff1a; 小示例 首先&#xff0c;引入依赖 然后&#xff0c;按照我们刚刚说的构建多线程的步骤进行构建&#…

Python实现天气数据采集

Python实现天气数据采集 一、需求介绍二、完整代码一、需求介绍 本次天气数据采集的需求是获取每日的最高温、最低温、风力、风向、天气状况、AQI指数,如图所示,完整代码附后: 本次采集的目标网址是2345天气网: 上图的URL中,beijing是城市名称的缩写,54511即为城市代码…

跨域计算芯片,一把被忽视的汽车降本尖刀

作者 |王博 编辑 |德新 2019年前后&#xff0c;「中央运算单元区域控制」的架构被提出。基于这一趋势&#xff0c;从板级的多芯片&#xff0c;到板级的单芯片&#xff0c;集成度越来越高&#xff0c;跨域计算芯片随之来到聚光灯下。 跨域计算芯片的特点是&#xff0c;与专为智…

java8总结

java8总结 java8新特性总结1. 行为参数化2. lambda表达式2.1 函数式接口2.2 函数描述符 3. Stream API3.1 付诸实践 java8新特性总结 行为参数化lambda表达式Stream Api 1. 行为参数化 定义&#xff1a;行为参数化&#xff0c;就是一个方法接受多个不同的行为作为参数&#x…

如何巧妙利用APP广告变现策略,提升用户参与度并实现盈利增长?

如何巧妙利用APP广告变现策略&#xff0c;提升用户参与度并实现盈利增长&#xff1f; 在竞争激烈的移动应用市场中&#xff0c;APP广告变现已成为开发者重要的盈利模式之一。为了吸引用户使用APP并实现有效的变现&#xff0c;开发者需要采取一系列巧妙的策略&#xff0c;确保…

【Qt问题】QStringLiteral、QString、QLatin1String简单区分

【Qt问题】QStringLiteral、QString、QLatin1String简单区分 最近在看项目代码的时候&#xff0c;一个频繁使用的关键词——“QStringLiteral”&#xff0c;引起了我的注意&#xff0c;关键是我竟然对它非常模糊&#xff0c;这不是一个Qter能够轻易接受的事情。 于是我秉承着…

【kubernetes】多 master 高可用集群架构部署

目录 前言 一、环境部署 二、master02 节点部署 1、拷贝相关文件 2、修改配置文件 3、启动各服务并设置开机自启 4、 查看node节点状态 三、负载均衡部署 1、部署 nginx 服务 1.1 编译安装 nginx 1.2 修改 nginx 配置文件 2、部署 keepalived 服务 2.1 yum安装 ke…

笔记88:LeetCode_134_加油站

前言&#xff1a; 前言1&#xff1a;这个题的题目条件给的不太严谨&#xff0c;题目描述中说“如果存在解&#xff0c;则保证它是唯一的”&#xff0c;通过我的实践&#xff0c;我发现这句话的意思其实是本题的所有样例只有两种情况&#xff0c;无解/有唯一解&#xff1b;而不可…

医院是自建档案室还是档案寄存好呢

医院可以选择自建档案室或档案寄存&#xff0c;具体选择取决于医院的需求和资源。 自建档案室意味着医院会拥有自己的档案空间和设施&#xff0c;可以更方便地管理和保管档案。这种方式可以确保医院对档案的访问和控制有更多的自主权&#xff0c;同时也能够根据医院的需求进行档…

5月23日学习记录

[CSAWQual 2019]Unagi 涉及&#xff1a;xxe漏洞&#xff0c;外来编码xml绕过 打开环境&#xff0c;发现存在文件上传 简单上传一个php 毫无疑问上传失败&#xff0c;说是存在waf&#xff0c;绕过waf才能上传&#xff0c;点击here看看 xml编码&#xff0c;可能存在xxe漏洞&…

Java并发: 锁和同步

在Java并发: 面临的挑战那一篇中我们提到锁和同步是实现并发安全(可见性/原子性)的方法之一。这一章我们来讲讲Java中的锁和同步的各种工具&#xff0c;包括: LockSupportAbstractQueuedSynchronizerJava内置的锁实现 1. LockSupport LockSupport是基于Unsafe的park/unpark实…

57. UE5 RPG 处理AI敌人转向以及拾取物品的问题

在上一篇文章中&#xff0c;我们实现了使用AI行为树控制敌人进行移动&#xff0c;它们可以一直跟随玩家&#xff0c;虽然现在还未实现攻击。但在移动过程中&#xff0c;我发现了有两个问题&#xff0c;第一个是敌人转向的时候很僵硬&#xff0c;可以说是瞬间转向的&#xff0c;…

鸿蒙开发接口应用程序包管理:【ApplicationInfo】

ApplicationInfo 说明&#xff1a; 本模块首批接口从API version 7 开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 开发前请熟悉鸿蒙开发指导文档&#xff1a; gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md点击或者复制转到。…

vue3结合element-plus之如何优雅的使用表单组件

背景 在日常开发中,我们会经常使用 element-ui 或者是 antdesign 或者是 element-plus 等组件库实现搜索功能 这里就需要用到相关表单组件 下面就以 element-plus 为例,我们实现一个搜索功能的组件,并且随着屏幕尺寸的变化,其布局也会跟随变化 最终大致效果如下: 这里…

MySQL之Schema与数据类型优化(三)

Schema与数据类型优化 BLOB和TEXT类型 BLOB和TEXT都是为存储很大的数据而设计的字符串数据类型&#xff0c;分别采用二进制和字符方式存储。 实际上它们分别属于两组不同的数据类型家族:字符类型是TINYTEXT&#xff0c;SMALLTEXT,TEXT&#xff0c;MEDIUMTEXT&#xff0c;LONG…

成都爱尔周进院长提醒当双眼度数差距过大,我们该做些什么

每个人的用眼方式、用眼习惯且两只眼睛“天生条件”不一定相同&#xff0c;当发生近视&#xff0c;双眼近视程度也就可能不同&#xff0c;双眼度数必然会变得不一样。当双眼度数产生差异&#xff0c;尤其是当双眼度数差别过大时会引发哪些问题&#xff1f; 双眼度数不一致&…

Qt快速入门到熟练(电子相册项目(二))

上一节我们成功实现了创建项目的向导界面的开发&#xff0c;这节我们继续去实现电子相册的其他功能。 新建DirTreeWidget类 还记得在Qt快速入门到熟练(电子相册项目(一))-CSDN博客里面&#xff0c;我们是在QDockWidget中添加了一个treeWidget作为以后显示目录树的空间…

OpenHarmony集成OCR三方库实现文字提取

1. 简介 Tesseract(Apache 2.0 License)是一个可以进行图像OCR识别的C库&#xff0c;可以跨平台运行 。本样例基于Tesseract库进行适配&#xff0c;使其可以运行在OpenAtom OpenHarmony&#xff08;以下简称“OpenHarmony”&#xff09;上&#xff0c;并新增N-API接口供上层应…

[算法] 优先算法(二): 双指针算法(下)

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏:&#x1f355; Collection与数据结构 (91平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm1001.2014.3001.5482 &#x1f9c0;Java …

Rust学习心得

我分享一下一年的Rust学习经历&#xff0c;从书到代码都一网打尽。 关于新手如何学习Rust&#xff0c;我之前在Hacker News上看到了这么一篇教程&#xff1a; 这篇教程与其他教程不同的时&#xff0c;他不是一个速成教程&#xff0c;而是通过自己的学习经历&#xff0c;向需要…