常用的设计模式之一(创建型模式)

news2024/10/7 4:24:43

设计模式可分为三大类:

  1. 创建型模式 (Creational Patterns)
  2. 结构性模式 (Structural Patterns)
  3. 行为型模式 (Behavioral Patterns)
模式描述包括
创建型模式工厂模式(Factory Pattern)
抽象工厂模式(Abstract Factory Pattern)
单例模式(Singleton Pattern)
建造者模式(Builder Pattern)
原型模式(Prototype Pattern)
结构型模式适配器模式(Adapter Pattern)
桥接模式(Bridge Pattern)
过滤器模式(Filter、Criteria Pattern)
组合模式(Composite Pattern)
装饰器模式(Decorator Pattern)
外观模式(Facade Pattern)
享元模式(Flyweight Pattern)
代理模式(Proxy Pattern)
行为型模式责任链模式(Chain of Responsibility Pattern)
命令模式(Command Pattern)
解释器模式(Interpreter Pattern)
迭代器模式(Iterator Pattern)
中介者模式(Mediator Pattern)
备忘录模式(Memento Pattern)
观察者模式(Observer Pattern)
状态模式(State Pattern)
空对象模式(Null Object Pattern)
策略模式(Strategy Pattern)
模板模式(Template Pattern)
访问者模式(Visitor Pattern)

我们将详细阐述一下三大类其中比较常用的设计模式,并简要分析一下利弊。

文章目录

  • 创建型模式
    • 工厂模式
      • 简单工厂模式(Simple Factory Pattern)
      • 工厂方法模式(Factory Method Pattern)
      • 抽象工厂模式(Abstract Factory Pattern)
    • 单例模式(Singleton Pattern)

创建型模式

工厂模式

什么是工厂模式呢?首先我们来看一下工厂模式的定义:

在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

  • 该模式的动机在于:
    定义一个创建对象的接口,通过不同的参数传递,让其子类决定具体创建哪一类型的实例,工厂模式让对象的创建过程延迟到了子类过程创建。对用户来讲,不用关心对象是怎么创建的,只需要知道不同的参数条件便可触发创建不同的实例即可。

  • 应用场景:
    1.日志记录器:对于用户来讲,日志可以保存到本地硬盘、系统事件、远程服务器,而为了将日志记录器和系统的其他功能解耦合,故可用日志记录器,只暴露一个接口传递参数,让工厂类创建实例即可。
    2.数据库访问:对于用户来讲,用户可能不知道系统最终会选择什么数据库,以及数据库可能产生变化时,故可使用工厂模式,隐藏数据库创建过程,暴漏接口供系统调用。
    3.设计一个连接服务器的框架,需要三个协议,“POP3”、“IMAP”、“HTTP”,可以把这三个作为产品类,共同实现一个接口。

可以拿富士康工厂来举例。

简单工厂模式(Simple Factory Pattern)

  • 工厂说明
    在富士康中会生产很多类型的手机,比如苹果、三星、诺基亚等等牌子的手机,工厂可随意指定生产线生产某一个品牌的手机。

  • UML图

在这里插入图片描述

  • 结构组成
    模式结构包括如下:

    • Factory:工厂角色
      工厂角色负责实现创建所有实例的内部逻辑
    • Product:抽象产品角色
      抽象产品角色是所创建的所有对象的父类,负责描述所有实例所共有的公共接口
    • ConcreteProduct:具体产品角色
      具体产品角色是创建目标,所有创建的对象都充当这个角色的某个具体类的实例。
  • 简单工厂的缺点
    扩展性非常差,当需要添加新的产品时,需要更改工厂类,违背了开放-封闭原则(软件实体(类、模块、函数等等)应该可以扩展,但是不可以修改。)

  • 简单工厂代码
    Phone()为抽象类,用于子类的共同函数,开放接口为show(),用于显示品牌信息。
    ApplePhone()、SamsungPhone()、NokiaPhone()为子类,具体类实现过程在此类中实现。

#include <iostream>
#include <string>
class Phone{
public:
    virtual ~Phone() {}
    virtual void show() = 0;
};

class ApplePhone : public Phone {
public:
    void show() {
        std::cout << "ApplePhone created" << std::endl;
    }
};
class SamsungPhone : public Phone {
public:
    void show() {
        std::cout << "SamsungPhone created" << std::endl;
    }
};
class NokiaPhone : public Phone {
public:
    void show() {
        std::cout << "NokiaPhone created" << std::endl;
    }
};
enum PhoneType
{
    APPLE,
    SAMSUNG,
    NOKIA
};
class PhoneFactory {
public:
    Phone* createPhone(PhoneType phone_type) {
        switch (phone_type)
        {
        case APPLE:
            return new ApplePhone();
        case SAMSUNG:
            return new SamsungPhone();
        case NOKIA:
            return new NokiaPhone();
        default:
            return nullptr;
        }
    }
};
int main()
{
    PhoneFactory phoneFactory;
    Phone* pApplePhone = phoneFactory.createPhone(APPLE);
    if (pApplePhone) {
        pApplePhone->show();
        delete pApplePhone;
        pApplePhone = nullptr;
    }
    return 0;
}

运行结果:

ApplePhone created

工厂方法模式(Factory Method Pattern)

  • 模式动机
    现在对该系统进行修改,不再设计一个工厂类来统一负责所有产品的创建,而是将具体手机的创建过程交给专门的工厂子类去完成,我们先定义一个抽象的手机工厂类,再定义具体的工厂类来生成苹果手机、三星手机、诺基亚手机等,它们实现在抽象手机工厂类中定义的方法。这种抽象化的结果使这种结构可以在不修改具体工厂类的情况下引进新的产品,如果出现新的手机类型,只需要为这种新类型的按钮创建一个具体的工厂类就可以获得该新牌子手机的实例,这一特点无疑使得工厂方法模式具有超越简单工厂模式的优越性,更加符合“开闭原则”。
    工厂方法模式和简单工厂模式的区别在于,工厂方法将创建具体实例的过程封装到了具体工厂类中,由具体的工厂类来实现某一个产品的创建。当有新的产品需要创建时,只需添加新的工厂类即可。

  • 模式定义
    工厂方法模式(Factory Method Pattern)又称为工厂模式,也叫虚拟构造器(Virtual Constructor)模式或者多态工厂(Polymorphic Factory)模式,它属于类创建型模式。在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。

  • XML结构图
    在这里插入图片描述

  • 模式结构:

    • Product:抽象产品 Phone()
    • ConcreteProduct:具体产品
    • Factory:抽象工厂PhoneFactory()
    • ConcreteFactory:具体工厂
  • 优点:

    1. 用户只需关注具体某一种产品的实现,对其他产品的实例化过程进行隐藏。
    2. 所有具体类都共用同一个抽象类
    3. 当有新的产品需求时,只需增加新的具体产品类和新的具体工厂类,不用对抽象类进行删改。满足了开放-封闭原则
  • 缺点:

    1. 在增加新的产品时,需要同时增加具体产品类和具体工厂类,增加了系统的编译负担。
    2. 在创建实例时,需要将抽象类暴漏给用户,因为有太多抽象类,不容易让用户理解。
  • 工厂方法模式代码

#include <iostream>
#include <string>
class Phone {
public:
    virtual ~Phone() {}
    virtual void show() = 0;
};

class ApplePhone : public Phone {
public:
    void show() {
        std::cout << "ApplePhone created" << std::endl;
    }
};
class SamsungPhone : public Phone {
public:
    void show() {
        std::cout << "SamsungPhone created" << std::endl;
    }
};
class NokiaPhone : public Phone {
public:
    void show() {
        std::cout << "NokiaPhone created" << std::endl;
    }
};

class PhoneFactory {
public:
    virtual ~PhoneFactory() {}
    virtual Phone* createPhone() = 0;
};
class AppleFactory : public PhoneFactory{
public:
    Phone* createPhone() {
        return new ApplePhone();
    }
};
class SamsungFactory : public PhoneFactory {
public:
    Phone* createPhone() {
        return new SamsungPhone();
    }
};
class NokiaFactory : public PhoneFactory {
public:
    Phone* createPhone() {
        return new NokiaPhone();
    }
};
int main()
{
    PhoneFactory* pPhoneFactory = new AppleFactory();
    Phone* pApplePhone = pPhoneFactory->createPhone();
    pApplePhone->show();
    delete pApplePhone;
    delete pPhoneFactory;
    return 0;
}

抽象工厂模式(Abstract Factory Pattern)

单例模式(Singleton Pattern)

TODO

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

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

相关文章

并发编程——可见性与有序性

如果有兴趣了解更多相关内容&#xff0c;欢迎来我的个人网站看看&#xff1a;耶瞳空间 JMM即Java Memory Model&#xff0c;它定义了主存、工作内存抽象概念&#xff0c;底层对应着CPU寄存器、缓存、硬件内存、CPU指令优化等。JMM体现在以下几个方面&#xff1a; 原子性&…

Web API

DOM API 1、选中页面元素 let elem document.querySelector(CSS选择器); console.log(elem); console.dir(elem); 2、事件 鼠标点击事件 onclick 鼠标移动事件 onmousemove 等等 事件源 .box&#xff0c;事件类型 onlick&#xff0c;事件处理方式 alert(hello) let d…

[Mybatis1]介绍与快速入门

文章目录 Mybatis概述 持久层 框架 Mybatis与JDBC对比 JDBC代码的缺陷 Mybatis简化JDBC Mybatis快速入门案例 整体案例项目结构 1.创建user表&#xff0c;添加数据 2.创建Maven项目&#xff0c;导入坐标 3.编写Mybatis核心配置文件 4.编写数据库返回对象的实体类 5. 编写S…

QML Button详解

1.Button简介 Button表示用户可以按下或单击的按钮控件。按钮通常用于执行一个动作&#xff0c;或回答一个问题。典型的按钮有确定、应用、取消、关闭、是、否和帮助。 Button继承自AbstractButton&#xff0c;提供了以下几种信号。 void canceled() //当按…

Python笔记 -- 列表

文章目录1、列表简介2、修改、添加、删除元素2.1、添加2.2、删除3、排序、倒序4、遍历列表5、创建数值列表6、列表切片7、列表复制8、元组1、列表简介 在Python中用方括号[]表示列表&#xff0c;用逗号隔开表示其元素 通过索引访问列表 names [aa,bb,cc,dd]print(names[0]) …

游戏项目中的程序化生成(PCG):算法之外的问题与问题

本篇讨论的是什么 从概念上讲&#xff0c;PCG&#xff08;程序化生成&#xff09;的含义很广&#xff1a;任何通过规则计算得到的内容&#xff0c;都可算作是PCG。但在很多游戏项目的资料&#xff0c;包括本篇&#xff0c;讨论PCG时特指是&#xff1a;用一些算法/工具(特别是H…

C语言-基础了解-13-C enum枚举

C enum枚举 一、C枚举 枚举是 C 语言中的一种基本数据类型&#xff0c;用于定义一组具有离散值的常量。&#xff0c;它可以让数据更简洁&#xff0c;更易读。 枚举类型通常用于为程序中的一组相关的常量取名字&#xff0c;以便于程序的可读性和维护性。 定义一个枚举类型&a…

3.2 LED闪烁流水灯蜂鸣器

LED闪烁1.1 电路连接示意图LED采用低电平点亮的方式&#xff0c;利用ST-Link的3.3V进行供电。1.2程序设计1.21知识储备GPIO配置步骤步骤&#xff1a;1. 第⼀步&#xff0c;使⽤RCC开启GPIO的时钟2. 第⼆步&#xff0c;使⽤GPIO_Init()函数初始化GPIO3. 第三步&#xff0c;使⽤输…

JavaWeb--会话技术

会话技术1 会话跟踪技术的概述2 Cookie2.1 Cookie的基本使用2.2 Cookie的原理分析2.3 Cookie的使用细节2.3.1 Cookie的存活时间2.3.2 Cookie存储中文3 Session3.1 Session的基本使用3.2 Session的原理分析3.3 Session的使用细节3.3.1 Session钝化与活化3.3.2 Session销毁目标 理…

java坦克大战(1.0)

坦克大战 后面开始学习怎么使用java制造一个坦克大战游戏 但是不是直接开始做&#xff0c;而是随着这个游戏程序的制造&#xff0c;一边学习新知识融入到游戏中。包括多线程&#xff0c;反射&#xff0c;IO流… Java坐标体系 在几乎所有的坐标中都有一个x轴和y轴&#xff0c…

大数据项目实战之数据仓库:用户行为采集平台——第1章 数据仓库概念

第1章 数据仓库概念 数据仓库&#xff08;Data Warehouse&#xff09;&#xff0c;是为企业制定决策&#xff0c;提供数据支持的。可以帮助企业改进业务流程、提高产品质量等。 数据仓库的输入数据通常包括&#xff1a;业务数据、用户行为数据和爬虫数据等 业务数据&#xf…

Java - 对象的比较

一、问题提出 前面讲了优先级队列&#xff0c;优先级队列在插入元素时有个要求&#xff1a;插入的元素不能是null或者元素之间必须要能够进行比较&#xff0c;为了简单起见&#xff0c;我们只是插入了Integer类型&#xff0c; 那优先级队列中能否插入自定义类型对象呢&#xf…

深入理解JDK动态代理原理,使用javassist动手写一个动态代理框架

文章目录一、动手实现一个动态代理框架1、初识javassist2、使用javassist实现一个动态代理框架二、JDK动态代理1、编码实现2、基本原理&#xff08;1&#xff09;getProxyClass0方法&#xff08;2&#xff09;总结写在后面一、动手实现一个动态代理框架 1、初识javassist Jav…

Dijkstra算法的入门与应用

目录 一、前言 二、Dijkstra算法 1、Dijkstra 算法简介 2、算法思想&#xff1a;多米诺骨牌 3、算法实现 4、例子 三、例题 1、蓝桥王国&#xff08;lanqiaoOJ题号1122&#xff09; 一、前言 本文主要讲了Dijkstra算法的概念、实现与一道模板例题。 二、Dijkstra算法…

RSTP基础要点(上)

RSTP基础RSTP引入背景STP所存在的问题RSTP对于STP的改进端口角色重新划分端口状态重新划分快速收敛机制&#xff1a;PA机制端口快速切换边缘端口的引入RSTP引入背景 STP协议虽然能够解决环路问题&#xff0c;但是由于网络拓扑收敛较慢&#xff0c;影响了用户通信质量&#xff…

分布式对象存储

参考《分布式对象存储----原理、架构以及Go语言实现》&#xff08;作者&#xff1a;胡世杰&#xff09; 对象存储简介 数据的管理方式 以对象的方式管理数据&#xff0c;一个对象包括&#xff1a;对象的数据、对象的元数据、对象的全局唯一标识符 访问数据的方式 可扩展的分…

useCallback、useMemo、React.memo

1、React.memo React.memo 是 React 中用于函数组件优化的高阶组件&#xff0c;可以在一定程度上减少组件的重渲染&#xff0c;提升应用性能。React.memo 的实现原理是对比组件的前后两次渲染传入的 props 是否相等&#xff0c;如果相等则不会触发重新渲染&#xff0c;否则会触…

使用 Nacos 搭建一个简单的微服务项目

Nacos Nacos 是阿里巴巴推出来的一个新开源项目&#xff0c;一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。 准备Nacos 将 nacos 安装成功之后&#xff0c;进入nacos的bin 目录下&#xff0c;通过命令sh startup.sh -m standalone启动nacos&#xff0c;然后…

ChatGPT概述:从模型训练到基本应用的介绍

ChatGPT概述&#xff1a;从模型训练到基本应用的介绍 目录 本文是对ChatGPT的由来、训练过程以及实际落地场景的解释&#xff0c;主要内容包括如下三个方面&#xff1a; 1、ChatGPT是什么 2、ChatGPT的原理 3、ChatGPT的思考 4、ChatGPT的应用 ChatGPT是什么 ChatGPT可能是近…

代码随想录算法训练营第四天| 24. 两两交换链表中的节点 、19.删除链表的倒数第N个节点、面试题 02.07. 链表相交 、142.环形链表II

24. 两两交换链表中的节点 24.两两交换链表中的节点介绍给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节点交换&#xff09;。思路上述是自己看到这道…