首页 > 其他分享 >设计模式

设计模式

时间:2023-09-03 09:55:27浏览次数:32  
标签:Singleton 函数 对象 模式 TaskQueue 单例 设计模式

1 类与类之间的关系

  • 继承(泛化)
  • 组合:整体对象可以控制成员对象的生命周期,一旦主体对象不存在,成员对象也不存在,整体对象和成员对象之间具有同生共死的关系,例如人的头部与眼、耳朵
  • 聚合:成员对象是整体的一部分,但是成员对象可以脱离主体对象独立存在。主体对象析构到的时候成员对象依旧可以存在,例如森林和动物、植物,没有森林的地方依旧可以有动植物
  • 关联:通常是一个类对象,作为另一个类的成员。有单向关联、双向关联、自关联三种
  • 依赖:大多数情况下依赖关系体现在某个类的方法使用另一个类的对象作为参数。

联和聚合的区别主要在于语义上:关联的两个对象之间一般是平等的,聚合和组合则一般是不平等的。
上述类之间的关系强弱由上到下依次减弱

2 设计模式三原则

首先明确类是什么:一组相关属性和行为的集合

单一职责原则

类的功能尽量单一,不要试图让一个类做很多事情,否则其功能发生变化时会变得难以维护

开放封闭原则(多态)

可以扩展,但是不可以修改。通常是在旧类中预留一个接口(虚函数或纯虚函数),在子类中进行重写,其实就是多态,当这个类遇到自己无法解决的问题时,可以找其它类来帮忙。

依赖倒转原则(多态)

  • 高层模块不应该依赖低层模块,两个都应该依赖抽象。
  • 抽象不应该依赖细节,细节应该依赖抽象。

对于第一条可以举个例子,我们的程序中大量使用了某个API,但是在后续开发中发现用另一种API更合适,但是这个时候程序是很难维护的。这里面高层模块可以认为是程序,低层模块是我们调用的API,如果在两层之间加入一个抽象,通过虚函数来实现具体使用哪一个API就会易于维护

对于第二条可以用里氏代换原则来判断,如果不满足里氏代换原则就不满足依赖倒转原则的第二条。里氏代换原则是指:子类如果想要替代父类对象,父类的规则(属性)必须同样适用于子类对象

2 单例模式

如果在一个类中存在大量全局变量,这里用一下那里也用一下,会让程序看起来很糟糕,比较合适的做法是提供一个唯一的接口来访问。

在一个项目中,全局范围内,某个类的实例有且仅有一个,通过这个唯一实例向其他模块提供数据的全局访问,这种模式就叫单例模式。

如果使用单例模式,首先要保证这个类的实例对象有且仅有一个,那么就需要采取一定的手段来限制类创建对象,涉及一个类多对象操作的函数有以下几个:

  • 构造函数:创建一个新的对象
  • 拷贝构造函数:根据已有对象拷贝出一个新的对象
  • 拷贝赋值操作符重载函数:两个对象之间的赋值

可进行的处理如下:
1.构造函数私有化,在类内部只调用一次,这个是可控的。

2.由于使用者在类外部不能使用构造函数,所以在类内部创建的这个唯一的对象必须是静态的,这样就可以通过类名来访问了,为了不破坏类的封装,我们都会把这个静态对象的访问权限设置为私有的。

  • 在类中只有它的静态成员函数才能访问其静态成员变量,所以可以给这个单例类提供一个静态函数用于得到这个静态的单例对象。
  • 拷贝构造函数私有化或者禁用(使用 = delete)

3.拷贝赋值操作符重载函数私有化或者禁用(从单例的语义上讲这个函数已经毫无意义,所以在类中不再提供这样一个函数,故将它也一并处理一下。)

// 定义一个单例模式的类
class Singleton
{
public:
    // = delete 代表函数禁用, 也可以将其访问权限设置为私有
    Singleton(const Singleton& obj) = delete;
    Singleton& operator=(const Singleton& obj) = delete;
    static Singleton* getInstance();
private:
    Singleton() = default;
    static Singleton* m_obj;
};
//初始化
Singleton *Singleton::m_obj = new Singleton;//内部成员可以调用私有函数 

饿汉模式与懒汉模式

单例模式的具体实现有两种:懒汉模式和饿汉模式,在上述的实现中,就是典型的饿汉模式。

饿汉模式就是在程序启动时就被创建并初始化,这样就得到了一个唯一的可用对象,饿汉模式可以确保没有线程安全问题,多线程可以同时访问。

这里说的多线程安全是因为它的创建和初始化在程序启动阶段就完成了,因此不需要在线程间进行并发的初始化操作,保证了单例模式的唯一性,如果涉及到对实例对象数据修改的问题,那么就要另外采取措施了

 
懒汉模式是在类加载的时候不去创建这个唯一的实例,而是在需要使用的时候再进行实例化。懒汉模式是有线程安全问题的,多个线程可能会同时检测到单例对象没有创造出来,同时去创建就造成了多个实例对象同时存在,违背了单例的原则

class TaskQueue
{
public:
    // = delete 代表函数禁用, 也可以将其访问权限设置为私有
    TaskQueue(const TaskQueue& obj) = delete;
    TaskQueue& operator=(const TaskQueue& obj) = delete;
    static TaskQueue* getInstance()
    {
        if(m_taskQ == nullptr)
        {
            m_taskQ = new TaskQueue;
        }
        return m_taskQ;
    }
private:
    TaskQueue() = default;
    static TaskQueue* m_taskQ;
};
TaskQueue* TaskQueue::m_taskQ = nullptr;

4 工厂模式

简单工厂模式

只有一个工厂类和工厂函数,工厂函数根据指定类生产不同的对象。它的缺点是不符合开闭原则,因为想让工厂生产新的对象时,需要修改已有的工厂类中的工厂函数

工厂模式

要生产n个对象就需要n个工厂,每个工厂只负责生产一种对象。主要是定义一个工抽象类,再建立多个子工厂,通过多态的方式使得可以动态指定哪个工厂来生产

抽象工厂模式

对于每个对象的不同属性再指定抽象类来实现

标签:Singleton,函数,对象,模式,TaskQueue,单例,设计模式
From: https://www.cnblogs.com/dreamer-q/p/17663565.html

相关文章

  • 设计模式:迭代器模式
    设计模式wiki中将设计模式分为四类,分别是:创建模式(creationalpatterns)结构模式(structuralpatterns)行为模式(behavioralpatterns)并发模式(concurrencypatterns)迭代器模式属于其中的行为模式。迭代器做的只有一件事,就是解决集合的遍历问题。以下是wiki对迭代器模式的概括......
  • 设计模式学习1 设计原则
    设计原则1.开闭原则对扩展开放,修改关闭。在程序需要扩展的时候,不能去修改原有代码,实现一个热插拔的效果。为了使程序的扩展性好,易于维护和升级为了达到这样的效果,我们需要使用接口和抽象类2.里氏代换原则任何基类可以出现的地方,子类一定可以出现。也就是子类继承父类时,除了添......
  • 【23种设计模式】单例模式(一)
    前言:单例模式是创建型模式5种中的第1种,关注对象的创建,保证一个类仅有一个实例,并且提供一个全局访问点。在软件系统中,经常有这样一些特殊的类,必须保证它们在系统中只存在一个实例,才能确保它们的逻辑正确性、以及良好的效率。如何绕过常规的构造器,提供一种机制来保证一个类只创建一......
  • 设计模式:观察者模式/发布-订阅模式
    设计模式wiki中将设计模式分为四类,分别是:创建模式(creationalpatterns)结构模式(structuralpatterns)行为模式(behavioralpatterns)并发模式(concurrencypatterns)观察者/发布订阅模式属于其中的行为模式。实际情境公众号订阅说到发布订阅,拿微信公众号举例,就很好理解,有n个......
  • 设计模式-创建型-原型模式
    title:设计模式-创建型-原型模式keywords:设计模式cover:[https://s1.ax1x.com/2023/08/31/pP01Vit.png]#sticky:10banner:type:imgbgurl:https://s1.ax1x.com/2023/08/31/pP01Vit.pngbannerText:设计模式-创建型-原型模式categories:设计模式tags:-......
  • 设计模式-创建型-单例模式
    title:设计模式-创建型-单例模式keywords:设计模式cover:[https://s1.ax1x.com/2023/08/31/pP01Vit.png]#sticky:10banner:type:imgbgurl:https://s1.ax1x.com/2023/08/31/pP01Vit.pngbannerText:设计模式-创建型-单例模式categories:设计模式tags:-......
  • 23种设计模式之代理模式
    代理设计模式(ProxyDesignPattern)是一种结构型设计模式,它为其他对象提供一个代理,以控制对这个对象的访问。代理模式可以用于实现懒加载、安全访问控制、日志记录等功能。在设计模式中,代理模式可以分为静态代理和动态代理。静态代理是指代理类在编译时就已经确定,而动态代理是指代理......
  • 23种设计模式之建造者模式
    Builder模式,也叫生成器模式。创建者模式主要包含以下四个角色:产品(Product):表示将要被构建的复杂对象。抽象创建者(AbstractBuilder):定义构建产品的接口,通常包含创建和获取产品的方法。具体创建者(ConcreteBuilder):实现抽象创建者定义的接口,为产品的各个部分提供具体实现。指挥者(Direc......
  • 23种设计模式之工厂模式
    工厂模式分为三种更加细分的类型:简单工厂、工厂方法和抽象工厂。简单工厂(SimpleFactory):简单工厂叫作静态工厂方法模式(StaticFactoryMethodPattern)。假设一个场景,需要一个资源加载器,要根据不同的url进行资源加载,但是如果将所有的加载实现代码全部封装在了一个load方法中,就会导致......
  • 23种设计模式之单例模式
    单例设计模式(SingletonDesignPattern):一个类只允许创建一个对象(或者实例),那这个类就是一个单例类,这种设计模式就叫作单例设计模式。如何实现一个单例:常见的单例设计模式,有如下五种写法,在编写单例代码的时候要注意以下几点:1、构造器需要私有化2、暴露一个公共的获取单例对象的接口3......