设计模式(2)创造型设计模式

创建型模式

  • 创建型模式
      • 1.工厂模式
          • 1.1 抽象工厂模式(Abstract factory)
          • 1.2 工厂方法模式(Factory Method)
          • 1.3 简单工厂模式(Simple Factory)
      • 2. 建造者模式(Builder)
      • 3. 原型模式(Prototypes)
      • 4. 单例模式
      • 5. 创建型模式之间的联系和区别

创建型模式

前提:为一个电脑游戏创建一个迷宫,忽略迷宫的诸多细节,仅仅关注迷宫是怎样被创建的。

定义:将迷宫定义为一系列房间(Room),房间的四面要么是一堵墙(Wall),要么是一扇门(Door)。

//房间四个面
enum Direction{ North, South, East, West};
//房间
class Room{...}
//墙
class Wall{...}
//门
class Door{...}
//迷宫
class Maze{...}
//迷宫游戏
class MazeGame{...}

一个简单的迷宫创建函数,如下:

Maze* MazeGame::CreateMaze()
{Maze *aMaze = new Maze;Room *r1 = new Room(1);Room *r2 = new Room(2);Door *dr = new Door(r1,r2);aMaze->addRoom(r1);aMaze->addRoom(r2);r1->setSide(North, new Wall);r1->setSide(South, dr);r1->setSide(East, new Wall);r1->setSide(West, new Wall);r2->setSide(North, new Wall);r2->setSide(North, new Wall);r2->setSide(North, new Wall);r2->setSide(North, dr);return aMaze;
}

这个函数的缺点在于: 对迷宫布局硬编码,改变布局意味着需要改变这个函数本身,容易产生错误,且不利于重利用。试想一下,重用该迷宫的布局,但是迷宫中的部件和来原来不一致了,例如现在的门是施了魔法的,需要咒语才能开启等等。在这种情况下,改变的最大障碍就是对被实例化的类进行硬编码。

创建型模型提供了多种不同方法从实例化它们的代码中除去对这些具体类的显示引用:

  1. 如果CreateMaze调用虚函数而不是显式构造来创建它需要的房间、门和墙壁;那么可以通过创建一个MazeGame的子类并重定义这些虚函数,从而改变被实列化的类。正如工厂方法模式
  2. 如果传递一个对象给CreateMaze作参数来创建房间、墙壁和门,那么可以通过传递不同的参数来改变这些部件的类。正如抽象工厂模式
  3. 如果传递一个对象给CreateMaze,这个对象可以在它所建造的迷宫中增加房间、墙壁和门的操作,来创建一个新的迷宫。那么可以通过继承当方式来改变迷宫被建造的方式,正如建造者模式
  4. 如果CreateMaze由多种原型的房间、墙壁和门对象参数化,它拷贝并将这些对象增加到迷宫中。正如原型模式
  5. 单例模式可以保证每个游戏中仅有一个迷宫存在,而且所有的游戏对象都可以迅速的访问它。

1.工厂模式

工厂模式定义:
工厂模式(Factory Pattern)是一种创建型设计模式,它提供了一种创建对象的接口,而无需指定它们具体的类,实例化的类是哪一个由子类决定。工厂模式将对象的实例化过程封装在一个工厂类中,使得客户端代码与具体类解耦,提供了一种灵活、可扩展的对象创建机制。

工厂模式的核心思想是将对象的创建过程封装在工厂类中,客户端代码通过与工厂类进行交互来获取所需的对象,而不需要直接实例化具体产品类。这种解耦的设计使得客户端代码更加灵活,可以通过切换具体工厂类来创建不同的产品对象。

工厂模式有以下几种常见的变体:

  1. 简单工厂模式(Simple Factory Pattern):使用一个单独的工厂类来创建所有的产品对象,通过传递不同的参数给工厂方法来选择创建哪种产品
  2. 工厂方法模式(Factory Method Pattern):每个具体产品都有对应的工厂类,客户端通过调用具体工厂类来创建具体产品对象
  3. 抽象工厂模式(Abstract Factory Pattern):提供一个抽象工厂接口,具体工厂类实现该接口并负责创建一系列相关或相互依赖的产品对象(把一系列工厂方法归结到一起)
1.1 抽象工厂模式(Abstract factory)

抽象工厂结构图:
在这里插入图片描述

在抽象工厂模式中,通常有以下几个角色:
抽象工厂(Abstract Factory):定义了创建产品的接口,包含了创建产品的抽象方法。
具体工厂(Concrete Factory):实现了抽象工厂接口,负责实际创建具体产品的对象。
抽象产品(Abstract Product):定义了产品的接口,是具体产品类的共同父类或接口。
具体产品(Concrete Product):实现了抽象产品接口,是工厂模式所创建的对象。

用抽象工厂来实现迷宫创建,代码如下:

class MazeFactory
{virtual Maze *MakeMaze(){return new Maze;}virtual Wall *MakeWall(){return new Wall;}virtual Room *MakeRoom(int n){return new Room(n);}virtual Door *MakeDoor(Room* r1, Room* r2){return new Door(r1,r2);}
}
//建造迷宫的程序使用MazeFactory作为参数,程序便能指定创建的房间、门、墙壁类型
Maze* MazeGame::CreateMaze(MazeFactor& factory)
{Maze *aMaze = factory.MakeMaze();Room *r1 = factory.MakeRoom(1);Room *r2 = factory.MakeRoom(2);Door *dr = factory.MakeDoor(r1,r2);aMaze->addRoom(r1);aMaze->addRoom(r2);r1->setSide(North, factory.MakeWall());r1->setSide(South, dr);r1->setSide(East, factory.MakeWall());r1->setSide(West, factory.MakeWall()l);r2->setSide(North, factory.MakeWall());r2->setSide(North, factory.MakeWall());r2->setSide(North, factory.MakeWall());r2->setSide(North, dr);return aMaze;
}
//创建一个MazeFactory的子类EnchanteMazeFactory,这是一个创建了施加魔法的迷宫工厂,EnchanteMazeFactory将重定义不同的成员函数并返回Room、Wall等不同的子类
class EnchanteMazeFactory : public MazeFactory
{...
}
//创建迷宫
MazeGame game;
EnchanteMazeFactory  factory;
game.CreateMaze(factory);
1.2 工厂方法模式(Factory Method)

工厂方式模式定义:
定义一个用于创建对象的接口,让子类决定实例化具体的类。Factory Method使一个类的实例化延迟到其子类中。

工厂方法结构图,如下:
在这里插入图片描述
适用性:

  • 当一个类不知道它所必须创建的对象的类的时候。
  • 当一个类希望由它的子类来指定它所创建的对象的时候。

工厂方法的一个潜在问题是它们可能为了创建适当的Product对象而迫使你创建Creator的子类,在c++种可以通过模板解决这种问题,如下:

class Creator
{virtual Product* CreateProduct() = 0 ;
}template <class TheProduct>
class StanderdCreator : public Creator
{virtual Product* CreateProduct();
}
template <class TheProduct>
Product* StanderdCreator<TheProduct>::CreateProduct()
{return new TheProduct;
}
//使用这个模板,客户只需要提供产品类
class MyProduct : public Product
{...
}
//使用
StanderdCreator<MyProduct> mycreator;

用工厂方法模式来实现迷宫创建,代码如下:

class MazeGame()
{Maze * CreateMaze();//工厂方法,推迟到子类中实现virtual Maze* makeMaze(){ return new Maze; }virtual Room* makeRoom(int n){ return new Room(n); }virtual Wall* makeWall(){ return new Wall; }virtual Door* makeDoor(Room* r1, Room* r2){ return new Door(r1,r2); }
}Maze* MazeGame::CreateMaze()
{Maze *aMaze = makeMaze();Room *r1 = makeRoom(1);Room *r2 = makeRoom(2);Door *dr = makeDoor(r1,r2);aMaze->addRoom(r1);aMaze->addRoom(r2);r1->setSide(North, makeWall());r1->setSide(South, dr);r1->setSide(East, makeWall());r1->setSide(West, makeWall());r2->setSide(North, makeWall());r2->setSide(North, makeWall());r2->setSide(North, makeWall());r2->setSide(North, dr);return aMaze;
}//不同的游戏可以创建MazeGame子类以特别指明一些迷宫的部件,MazeGame子类可以重定义所有或者部分工厂方法以指定产品中的变化,如下
class BombedMazeGame : public MazeGame
{virtual Wall* makeWall(){ return new BombedWall; }virtual Room* makeRoom(int n){ return new RoomWithABomb(n); }
}
1.3 简单工厂模式(Simple Factory)

简单工厂模式定义:也称为静态工厂模式,是一种创建型设计模式,它通过一个工厂类来封装对象的创建过程,根据客户端的请求返回不同的具体对象。简而言之就是在实现过程中通过指定参数来创建相应的产品。

class Creator
{virtual Product* Create(ProductId id){if(id == MINE) return new MyProduct;if(id == YOURS) return new YoursProduct;return 0;}
}
//子类可以重写Product,并引入新的标识
class MyCreator : public Creator
{virtual Product* Create(ProductId id){if(id == MINE) return new YoursProduct;if(id == YOURS) return new MyProduct;if(id == THRIRS) return new ThierProduct;return Creator::Create(id);return 0;}
}

2. 建造者模式(Builder)

建造者模式的定义:将一个复杂对象的构建与其表示(定义)分离,使得同样的构建过程可以创建不同的表示。
建造者模式的核心思想是将一个复杂对象的构建过程分解为多个简单的步骤,每个步骤由具体建造者来实现。通过指挥者将这些步骤按照一定的顺序组合起来,最终构建出一个完整的复杂对象。这样,客户端代码只需要与指挥者进行交互,而无需关心具体的构建过程和细节。

建造者模式适用于以下情况:

  • 当需要创建的对象具有复杂的内部结构,且内部部件的构建顺序和组合方式不稳定或多变时。
  • 当需要创建的对象的配置选项较多,构造函数参数过多且难以维护时。
  • 当希望通过一种统一的方式构建不同表示的对象时。

建造者模式结构图:
在这里插入图片描述
用建造者模式来实现迷宫创建,代码如下:

//MazeBuilder类定义下面的接口来创建迷宫
class MazeBuilder
{//复杂对象的构建过程分解为多个简单的步骤,每个步骤由具体建造者来实现virtual void BuildMaze(){}virtual void BuildRoom(int n){}virtual void BuildDoor(int roomFrom, int rootTo){}virtual Maze* GetMaze(){return 0;}
};Maze* MazeGame::CreateMaze(MazeBuilder& builder)
{builder.BuildMaze();builder.BuildRoom(1);builder.BuildRoom(2);builder.BuildDoor(1,2);return builder.GetMaze();
}
//子类StandarMazeBuilder实现了简单迷宫的创建
class StandarMazeBuilder : public MazeBuilder
{...
}
//创建迷宫
Maze * maze;
MazeGame game;
StandarMazeBuilder  builder;
maze = game.CreateMaze(builder);

3. 原型模式(Prototypes)

原型模式定义:原型模式(Prototype Pattern)是一种创建型设计模式,它通过复制现有对象来创建新的对象,而无需通过调用构造函数来创建。原型模式基于对象的克隆来创建新的对象,可以避免重复创建相似对象的开销。

原型模式的优点包括:

  • 可以避免重复创建相似对象的开销,提高创建对象的效率。
  • 可以通过克隆来动态地创建对象,无需依赖具体类。
  • 可以在运行时动态添加和删除原型对象。

原型模式的主要缺陷:每一个Protoypes子类都必须实现Clone操作,当类已经存在时就难以新增Clone操作,或当内部包括一些不支持拷贝或由循环引用的对象时,实现克隆可能会很困难。

原型模式特别适用于以下情形:

  • 创建一个对象需要消耗的资源较多,如数据读取、硬件访问等,可以通过原型复制来提高性能
  • 系统需要大量相同或相似对象(例如,克隆已有对象,改变值以指定新对象)的时候,可通过复制原型的方式来减少创建对象的开销
  • 对象的状态满足上述描述,并且状态需要持续变化的场景中,可以选择原型模式。

原型模式结构图,如下:
在这里插入图片描述
当实现原型时,可以考虑下面一些问题:

  1. 使用一个原型管理器。使用一个注册表存储和检索原型。在克隆一个原型前向注册表请求该原型。原型管理器是一个关联存储器,它返回一个与给定关键字相匹配的原型。
  2. 原型需要实现clone操作。
  3. 原型clone后的初始化操作。

用原型模式来实现迷宫创建(相关类声明在抽象工厂章节),代码如下:

class MazePrototypeFactory : public MazeFactory
{MazePrototypeFactory(Maze* m, Wall* w, Room* r, Door* d){_prototypeMaze = m;_prototypeRoom = r;_prototypeWall = w;_prototpyeDoor = d;}virtual Maze *MakeMaze(){return _prototypeMaze->clone();}virtual Wall *MakeWall(){return _prototypeWall->clone();}virtual Room *MakeRoom(int n){Room* r = _prototypeRoom->clone();r->init(n);return r;}virtual Door *MakeDoor(Room* r1, Room* r2){Door* d = _prototpyeDoor->clone();d->init(r1,r2);return d;}Maze* _prototypeMaze;Room* _prototypeRoom;Wall* _prototypeWall;Door* _prototpyeDoor;
}//创建迷宫
MazeGame game;
MazePrototypeFactory factory(new Maze, new Wall, new Room, new Door);
Maze * maze = game.CreateMaze(factory);

4. 单例模式

单例模式定义:单例模式(Singleton Pattern)是一种创建型设计模式,它确保一个类只有一个实例,并提供了一个全局访问该实例的入口点。

单例模式优点:

  • 提供了对唯一实例的全局访问点,方便其他类使用该实例。
  • 避免了重复创建对象的开销,节省了系统资源。
  • 确保了对象的一致性,因为只有一个实例存在。

单例模式的两种实现:

  • 懒汉模式

    class Singletion;
    Singletion* Singletion::sing = NULL;
    class Singletion
    {
    public://方式1static Singletion *creat_singletion(){if (!sing){lock();if(!sing){sing = new Singletion();}unlock();}return sing;}//由于双检锁失败的原因,这里提供方式2static Singletion& create_singletion1(){static Singletion sing1;return sing1}void task(){cout << "singtion task ..." << endl;}
    private:Singletion();Singletion(Singletion&);Singletion(Singletion&&);Singletion& operator=(const Singletion&);static Singletion *sing;//添加无智能指针时删除https://www.cnblogs.com/ring1992/p/9592817.html
    }
    //单例模板https://www.cnblogs.com/sunchaothu/p/10389842.html
    
  • 饥汉模式

    class Singletion
    {
    public:Singletion* get_instance(){return sing;}	void task (){//task}
    private:Singletion();Singletion(Singletion&);Singletion(Singletion&&);Singletion& operator=(const Singletion&);static Singletion *sing;
    }
    Singletion* Singletion::sing = new Singletion();
    

5. 创建型模式之间的联系和区别

  1. Abstract Factory和Builder相似,两者都可以创建复杂的对象。主要的区别是builder模式着重于一步一步构造一个复杂对象,而Abstract Factory着重于多个系列的产品对象。
  2. Abstract Factory模式可以通过Factory Method模式或者Builder模式来实现。
  3. Prototype和Abstract Factory模式在某种方面是相互竞争的,但是它们也可以一起使用。Abstract Factory可以存储一个被克隆的原型集合,并且通过集合返回大量对象。
  4. 在一个框架系统中,用一个系统创建的抽象类对系统进行参数化(CreateMaze函数)的方式有两种:
    a.生成创建对象的子类,比如工厂方法模式,这种方法的缺点在于,如果要改变产品类,就需要创建一个新的子类。
    b.定义一个对象负责明确产品对象的类,并将它作为该系统的参数,比如抽象工厂、原型模式、建造者模式。抽象工厂由这个工厂对象产生多个类的对象;建造者由这个工厂对象使用一个复杂协议逐步创建一个复杂产品;原型模式由该工厂对象通过拷贝原型对象来创建产品。

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

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

相关文章

[Android]四大组件简介

在 Android 开发中&#xff0c;“四大组件”&#xff08;Four Major Components&#xff09;是指构成 Android 应用程序的四种核心组件&#xff0c;它们通过各自的方式与系统交互&#xff0c;实现应用的多样功能。这些组件是&#xff1a;Activity、Service、Broadcast Receiver…

6个月小猫成长必备!福派斯无麸质幼猫粮评测

你知道吗&#xff1f;给小猫选择适合的猫粮是一件非常不容易但很重要的事情。那么&#xff0c;对于6个月大的小猫来说&#xff0c;什么样的猫粮是最适合它们的呢&#xff1f;&#x1f431; 我们首先要考虑的是猫粮的营养成分。6个月大的小猫正处于快速生长期&#xff0c;所以需…

远程连接是什么?

远程连接是指通过网络连接两个或多个设备&#xff0c;实现远程访问、控制或传输数据的技术。它在现代科技发展中起到了重要作用&#xff0c;使得我们可以随时随地与远程设备进行交互、管理和操作。 天联组网是一种高效的远程连接解决方案&#xff0c;它因为操作简单、跨平台应用…

git使用注意事项事项

以下操作均在gitee平台上实现 文章目录 1、本地仓库和远程仓库有冲突2、git提交自动忽略某些文件3、git无法push提交到远程仓库 1、本地仓库和远程仓库有冲突 在web端修改了文件内容或者删除了文件&#xff0c;本地仓库需要重新把远程仓库拉取到本地&#xff0c;或者强制提交到…

Prometheus 2: 一个专门评估其他语言模型的开源语言模型(续集)

普罗米修斯的续集来了。 专有的语言模型如 GPT-4 经常被用来评估来自各种语言模型的回应品质。然而,透明度、可控制性和可负担性等考虑强烈促使开发专门用于评估的开源语言模型。另一方面,现有的开源评估语言模型表现出关键的缺点:1) 它们给出的分数与人类给出的分数存在显著差…

图像处理-图像平滑

图像平滑 前言一、概念介绍1.1 图像的平滑1.2 图像中噪声的分类1.3 MATLAB的添加噪音代码 二、空间域平滑滤波2.1 均值滤波2.2 原理计算 总结 前言 在图像的获取、传输和存储过程常常收到各种噪声的干扰和影响&#xff0c;使得图像的质量下降&#xff0c;为了获得高质量的数字…

读天才与算法:人脑与AI的数学思维笔记20_数学图灵测试

1. 数学图灵测试 1.1. 能不能将这种计算机证明语言翻译成易于与人交流的方式呢&#xff1f; 1.1.1. 剑桥大学的两位数学家蒂莫西高尔斯&#xff08;Timothy Gowers&#xff09;和莫汉加内萨林加姆&#xff08;Mohan Ganesalingam&#xff09;开展了此项研究 1.1.1.1. 他们决…

与Apolo共创生态: Apollo X企业自动驾驶解决方案的亮点

文章目录 前言技术革新的里程碑Apollo X企业自动驾驶解决方案的亮点Application X企业预制套件的多场景覆盖Studio X企业协同工具链的全周期支持第一阶段&#xff1a;上机系统构建第二阶段&#xff1a;POC搭建第三阶段&#xff1a;规模运营小结 共创生态&#xff0c;共享未来共…

Mysql数据在磁盘上的存储结构

一. 前言 一行数据的存储格式大致如下所示: 变长字段的长度列表&#xff0c;null值列表&#xff0c;数据头&#xff0c;column01的值&#xff0c;column02的值&#xff0c;column0n的值… 二. 变长字段 在MySQL里有一些字段的长度是变长的&#xff0c;是不固定的&#xff0c;…

ContEA阅读笔记

Facing Changes: Continual Entity Alignment for Growing Knowledge Graphs 面对变化&#xff1a;不断增长的知识图谱的持续实体对齐 Abstract 实体对齐是知识图谱(KG)集成中一项基本且重要的技术。多年来&#xff0c;实体对齐的研究一直基于知识图谱是静态的假设&#xff…

人工智能的发展将如何重塑网络安全

微信搜索关注公众号网络研究观&#xff0c;获取更多信息。 人们很容易认为人工智能 (AI) 真正出现是在 2019 年&#xff0c;当时 OpenAI 推出了 ChatGPT 的前身 GPT-2。 但现实却有些不同。人工智能的基础可以追溯到 1950 年&#xff0c;当时数学家艾伦图灵发表了题为“计算机…

微信小程序如何使用svg矢量图标

微信小程序如何使用自定义SVG矢量图标 在微信小程序中&#xff0c;经常会用到小图标来装饰界面&#xff0c;我们常用的方法就是引用第三方的图标&#xff0c;但会存在收费或者找不到合适的图标&#xff0c;这时候我建议可以自行编写svg图标代码&#xff0c;就可以随心所欲的使…

【一起深度学习——kaggle叶子分类】

kaggle 叶子分类 目的&#xff1a;将叶子进行分类。实现步骤&#xff1a;1、数据处理&#xff1a;2、加载数据3、 定义残差块4、定义Resnet模型。5、定义训练以及评估函数&#xff1a;6、开始训练&#xff1a;7、输出结果&#xff1a; 目的&#xff1a;将叶子进行分类。 实现步…

知识图谱:人工智能的“核心驱动力”

知识图谱&#xff1a;人工智能的“核心驱动力” 一、人工智能与知识图谱二、知识图谱的定义与重要性三、知识图谱工程师的薪资情况四、知识图谱的应用领域六、知识图谱的未来展望七、总结 一、人工智能与知识图谱 人工智能&#xff08;AI&#xff09;作为21世纪的前沿技术&…

设备树与/sys/bus/platform/devices与/sys/devices目录关系

设备树与sys/bus/platform/devices sysfs文件系统中/sys/bus/platform/devices下的设备是由设备树生成&#xff0c; 根节点下有compatible的子节点都会在/bus/platform/devices生成节点 总线 I2C、SPI 等控制器会在/bus/platform/devices生成节点 总线 I2C、SPI 节点下的子节点…

牛客网刷题 | BC78 KiKi说祝福语

目前主要分为三个专栏&#xff0c;后续还会添加&#xff1a; 专栏如下&#xff1a; C语言刷题解析 C语言系列文章 我的成长经历 感谢阅读&#xff01; 初来乍到&#xff0c;如有错误请指出&#xff0c;感谢&#xff01; 描述 2020年来到了&#…

【Qt】按钮类控件

文章目录 1 :peach:Push Button:peach:2 :peach:Radio Buttion:peach:3 :peach:Check Box:peach:4 :peach:Tool Button:peach: 1 &#x1f351;Push Button&#x1f351; 使⽤ QPushButton 表⽰⼀个按钮&#xff0c;这也是当前我们最熟悉的⼀个控件了&#xff0c;QPushButton …

SOL链DApp智能合约代币质押挖矿分红系统开发

随着区块链技术的不断发展和普及&#xff0c;越来越多的项目开始探索基于区块链的去中心化应用&#xff08;DApp&#xff09;。Solana&#xff08;SOL&#xff09;作为一条高性能、低成本的区块链网络&#xff0c;吸引了众多开发者和项目&#xff0c;其中包括了各种类型的DApp&…

Altium Designer——检查原理图库正确性并生成报告

一、方法&#xff1a; 1.打开原理图库&#xff1a; 2.点击菜单栏的报告选项&#xff1a; 3.选择器件规则检查&#xff1a; 根据需求勾选&#xff0c;一般都是全部勾选&#xff1a; 二、问题&#xff1a; 1.缺少封装会导致什么问题&#xff1a; 1.首先&#xff1a; 封装是…

MWeb Pro for Mac:功能强大的Markdown博客编辑器

MWeb Pro for Mac是一款功能强大的Markdown博客编辑器&#xff0c;专为Mac用户设计&#xff0c;提供了一站式的博客写作和发布体验。这款软件不仅支持Markdown语法&#xff0c;还提供了丰富的编辑和排版功能&#xff0c;让用户能够轻松创建出精美的博客内容。 MWeb Pro的即时预…