常见的几种设计模式

本文详细介绍了设计模式的六大原则,包括开闭原则、单一职责原则、里氏替换原则、依赖倒转原则、接口隔离原则和迪米特法则。接着,探讨了创建型模式中的单例模式、观察者模式和工厂模式,通过实例展示了它们的实现和应用场景。单例模式确保类只有一个实例,观察者模式实现了对象间的一对多依赖关系,而工厂模式则提供了创建对象的抽象。这些模式在软件设计中起着关键作用,有助于提高代码的可维护性和扩展性。
摘要由CSDN通过智能技术生成

01 设计模式六大原则

  • 开闭原则
    对扩展开放,对修改关闭。程序在修改时,不能修改原有的代码,而是要扩展原有的代码,实现热插拔的效果。

  • 单一职责原则
    一个类应该有且仅有一个引起它变化的原因,否则这个类应该被拆分。

  • 里氏替换原则(Liskov Substitution Principle)
    子类可以扩展父类的功能,但不能改变父类原有的功能。即子类继承父类时,除添加新的方法完成新增功能外,金陵不要重写父类的方法。

  • 依赖倒转原则(Dependence Inversion Principle)
    面向接口编程,依赖于抽象而不依赖于具体。写代码时用到具体类时,不与具体类交互,而与具体类的上层接口交互。

  • 接口隔离原则(Interface Segregation Principle)
    每个接口中不存在子类用不到却必须实现的方法,如果不然,就要将接口拆分。使用多个隔离的接口,比使用单个接口(多个接口方法集合到一个的接口)要好。

  • 迪米特法则/最少知道原则
    一个类对自己依赖的类知道的越少越好。也就是说无论被依赖的类多么复杂,都应该将逻辑封装在方法的内部,通过public方法提供给外部。这样当被依赖的类变化时,才能最小的影响该类。

  • 合成复用原则 (Composite Reuse Principle)
    尽量首先使用合成/聚合的方式,而不是使用继承。

02 创建型模式

2.1 单例模式

  • 定义
    一个类只有一个实例,该类能自行创建,且能对外提供一个访问单例的全局访问点的一种模式。

  • 优点

    • 可以保证内存中只有一个实例,减少了内存开销。
    • 可以避免对资源的多重占用。
    • 设置全局访问点,可以优化和共享资源的访问。
  • 缺点

    • 单例模式一般没有接口,扩展困难。如果要修改就要修改原来的代码,违背了了开闭原则。
    • 在并发测试中不利于代码调试。测试中如果单例中的代码没有执行完,不能模拟生成一个新的对象。
    • 单例模式的功能和代码通常在一个类中,如果设计不合理,则很容易违背开闭原则。
  • 应用场景

    • 需要频繁创建的类。使用单例可减少内存压力。
    • 需要只生成一个对象的时候。如军团最高长官,校长等。
    • 创建实例时占用资源较多,或者实例化耗时比较常。如在堆上实例化本地数据库对象。
    • 需要频繁实例化,且创建的对象又频繁被销毁。如多线程的线程池、网络连接池。
    • 对于一些控制硬件级别的操作,或单一控制逻辑的操作,多个实例对象会引起混乱。
    • 对象需要被共享的场合,如 WEB 中的配置对象、数据库的连接池。
  • 两种实现方式

    • 懒汉模式
      特点是在类加载时没有创建单例,只有当第一次调用实例化的方法时才创建这个单例,因此第一次调用时要进行一系列的初始化工作因此会有一定的延时,初始化完成之后就和饿汉模式用起来一样了。
      懒汉模式在多线程下是不安全的,不同的线程可能会创建创建不同的单例对象,需要通过加锁避免这种情况。

    • 饿汉模式
      特点是类一旦加载就创建一个单例,保证在调用实例化方法之前就已经存在了。
      饿汉模式在多线程下是安全的。

2.2 观察者模式

  • 定义
    指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
    MVC 模型就是依靠这种模式实现的。

  • 优点

    • 降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系,复合依赖倒置原则。
    • 目标与观察者之间建立了一套触发机制。
  • 缺点

    • 目标与观察者之间的依赖关系并没有完全截除,且可能出现循环引用。
    • 当观察者的对象很多时,通知的发布会花费很多时间,影响程序的效率。
  • 结构

    • 抽象主题(Subject):也叫抽象目标类,它提供一个用于保存观察者对象的聚合类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。
    • 具体主题(Concrete Subject):也叫具体目标,它实现抽象目标中的通知方法,当具体主题的内部状态发生变化时,通知所有注册过的观察者对象。
    • 抽象观察者(Observer):它是一个抽象类或接口,包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。
    • 具体观察者(Concrete Observer):实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时自动更新自身的状态。
      #include <iostream>
      #include <string>
      #include <vector>
      
      using namespace std;
      
      // 抽象主题声明
      class Subject;
      
      // 抽象观察者
      class Observer {
      protected:
          string name;
          Subject* sub;
      
      public:
          Observer(string& name, Subject* sub) {
              this->name = name;
              this->sub = sub;
          }
          virtual void update() = 0;
      };
      
      //具体的观察者
      class GameObserver : public Observer {
      public:
          GameObserver(string name, Subject* sub) :Observer(name, sub) {
          }
      
          void update();
      };
      
      //具体的观察者
      class NBAObserver : public Observer {
      public:
          NBAObserver(string name, Subject* sub) :Observer(name, sub) {
          }
          void update();
      };
      
      // 抽象通知者
      class Subject {
      protected:
          vector<Observer*> observers;
      public:
          string action;
          virtual void attach(Observer*) = 0;
          virtual void detach(Observer*) = 0;
          virtual void notify() = 0;
      };
      
      // 具体的通知者
      class ConcreteSubject : public Subject {
          void attach(Observer* observer) {
              observers.push_back(observer);
          }
      
          void detach(Observer* observer) {
              auto iter = observers.cbegin();
      
              for (; iter != observers.cend() && *iter != observer; ++iter);
              
              if (iter != observers.cend()) {
                  observers.erase(iter);
              }
          }
      
          void notify() {
              for (auto elem : observers) {
                  elem->update();
              }
          }
      };
      
      void GameObserver::update() {
          cout << name << "收到" << sub->action << "的消息了。" << endl;
      };
      
      void NBAObserver::update() {
          cout << name << "收到" << sub->action << "的消息了。" << endl;
      };
      
      int main() {
          // 创建观察者
          Subject* sub = new ConcreteSubject();
          // 创建被观察的对象
          Observer* obj1 = new GameObserver("张三", sub);
          Observer* obj2 = new NBAObserver("李四", sub);
          
          // 加入观察队列
          sub->attach(obj1);
          sub->attach(obj2);
      
          // 触发事件
          sub->action = "领福利";
          cout << "-- 开始下发" << sub->action << "的通知 --" << endl;
          sub->notify();
          
      
          // 触发事件
          sub->action = "上报材料";
          cout << "-- 开始下发" << sub->action << "的通知 --" << endl;
          sub->notify();
      }
      

2.3 工厂模式

简单工厂模式

对于不同的产品的创建定义一个工厂类,将产品的类型作为参数传入工厂的创建函数,根据类型分支选择不同的产品构造函数。

typedef enum ProductTypeTag {
    TypeA, 
    TypeB, 
} PRODUCY_TYPE;

class Product {
public:
    virtual void show() = 0;
};

class ProductA: public Product {
public:
    virtual void show() override {
        cout << "ProductA::show()" << endl;
    }
};

class ProductB: public Product {
public:
    virtual void show() override {
        cout << "ProductB::show()" << endl;
    }
};

class Factory {
public:
    Product *createPrduct(PRODUCY_TYPE type) {
        switch (type) {
        case TypeA:
            return new ProductA();
            break;
        case TypeB:
            return new ProductB();
            break;
        default:
            return nullptr;
            break;
        }
    }
};

int main() {
    Factory productCreator;
    Product *productA = productCreator.createPrduct(TypeA);
    Product *productB = productCreator.createPrduct(TypeB);
    productA->show();
    productB->show();
}
// ProductA::show()
// ProductB::show()

工厂方法模式

简单工厂模式只是简单的创建过程进行封装,工厂方法模式在简单工厂模式的基础上增加对工厂的基类抽象,不同的产品采用不同的工厂创建。

typedef enum ProductTypeTag {
    TypeA, 
    TypeB, 
} PRODUCY_TYPE;

class Product {
public:
    virtual void show() = 0;
};

class ProductA: public Product {
public:
    virtual void show() override {
        cout << "ProductA::show()" << endl;
    }
};

class ProductB: public Product {
public:
    virtual void show() override {
        cout << "ProductB::show()" << endl;
    }
};

class Factory {
public:
    virtual Product *createPrduct() = 0; 
};

class FactoryA: public Factory {
public:
    virtual Product *createPrduct() override {
        return new ProductA();
    }
};

class FactoryB: public Factory {
public:
    virtual Product *createPrduct() override {
        return new ProductB();
    }
};

int main() {
    Factory *factoryA = new FactoryA();
    Product *productA = factoryA->createPrduct();

    Factory *factoryB = new FactoryB();
    Product *productB = factoryB->createPrduct();

    productA->show();
    productB->show();
}
// ProductA::show()
// ProductB::show()

抽象工厂模式

工厂方法模式适用于产品种类结构单一的场合,为一类产品提供创建的接口;而抽象工厂方法适用于产品种类结构多的场合,就是当具有多个抽象产品类型时,抽象工厂便可以派上用场。

#include <iostream>
#include <string>
#include <vector>

using namespace std;

typedef enum ProductTypeTag {
	TypeA,
	TypeB,
} PRODUCY_TYPE;

class ProductA {
public:
	virtual void show() = 0;
};

class ProductA1 : public ProductA {
public:
	virtual void show() override {
		cout << "ProductA1::show()" << endl;
	}
};

class ProductA2 : public ProductA {
public:
	virtual void show() override {
		cout << "ProductA2::show()" << endl;
	}
};

class ProductB {
public:
	virtual void show() = 0;
};

class ProductB1 : public ProductB {
public:
	virtual void show() override {
		cout << "ProductB1::show()" << endl;
	}
};

class ProductB2 : public ProductB {
public:
	virtual void show() override {
		cout << "ProductB2::show()" << endl;
	}
};

class Factory {
public:
	virtual ProductA* createPrductA() = 0;
	virtual ProductB* createPrductB() = 0;
};

class Factory1 : public Factory {
public:
	ProductA* createPrductA() override {
		return new ProductA1();
	}
	ProductB* createPrductB() override {
		return new ProductB1();
	}
};

class Factory2 : public Factory {
public:
	ProductA* createPrductA() override {
		return new ProductA2();
	}
	ProductB* createPrductB() override {
		return new ProductB2();
	}
};

int main() {
	Factory* factory1 = new Factory1();
	ProductA* productA1 = factory1->createPrductA();
	ProductB* productB1 = factory1->createPrductB();
	productA1->show();
	productB1->show();

	Factory* factory2 = new Factory2();
	ProductA* productA2 = factory2->createPrductA();
	ProductB* productB2 = factory2->createPrductB();
	productA2->show();
	productB2->show();
}
// ProductA1::show()
// ProductB1::show()
// ProductA2::show()
// ProductB2::show()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值