2024年最全软件工程的23种设计模式_软件设计模式,2024年最新面试资料分享

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

#define PropertyBuilderByName(type, name, access\_permission)\
 access\_permission:\
 type m\_##name;\
 public:\
 inline void set##name(type v) {\
 m\_##name = v;\
 }\
 inline type get##name() {\
 return m\_##name;\
 }\

#define PointerPropertyBuilderByName(type, name, access\_permission)\
 access\_permission:\
 type\* m\_##name;\
 public:\
 inline void set##name(type\* v){\
 m\_##name = v;\
 }\
 inline type\* get##name(){\
 return m\_##name;\
 }\

设计模式

模式
在一定环境中解决某一问题的方案,包括三个基本元素–问题,解决方案和环境。
大白话:在一定环境下,用固定套路解决问题。

设计模式(Design pattern)
是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计 模式是为了可重用代码、让代码更容易被他人理解、保证代 码可靠性。 毫无疑问,设计模 式于己于他人于系统都是多赢的;设计模式使代码编制真正工程化;

设计模式的分类

创建型模式 : 通常和对象的创建有关,涉及到对象实例化的方式。(共 5 种模式)

结构型模式: 描述的是如何组合类和对象以获得更大的结构。(共 7 种模式)

行为型模式: 用来对类或对象怎样交互和怎样分配职责进行描述。(共 11 种模式)

创建型模式

该模式用来处理对象的创建过程,主要包含以下五种设计模式:(单原建抽象工厂)

1,工厂方法模式(Factory Method Pattern)的用意是定义一个创建产品对象的工厂接口, 将实际创建工作推迟到子类中。

2,抽象工厂模式(Abstract Factory Pattern)的意图是提供一个创建一系列相关或者相互依 赖的接口,而无需指定它们具体的类。

3,建造者模式(Builder Pattern)的意图是将一个复杂的构建与其表示相分离,使得同样的 构建过程可以创建不同的表示。

4,原型模式(Prototype Pattern)是用原型实例指定创建对象的种类,并且通过拷贝这些原 型创建新的对象。

5,单例模式(Singleton Pattern)是保证一个类仅有一个实例,并提供一个访问它的全局访 问点。

结构型模式

6,代理模式(Proxy Pattern)就是为其他对象提供一种代理以控制对这个对象的访问。

7,装饰者模式(Decorator Pattern)动态的给一个对象添加一些额外的职责。就增加功能来 说,此模式比生成子类更为灵活。

8,适配器模式(Adapter Pattern)是将一个类的接口转换成客户希望的另外一个接口。使得 原本由于接口不兼容而不能一起工作的那些类可以一起工作。

9,桥接模式(Bridge Pattern)是将抽象部分与实际部分分离,使它们都可以独立的变化。

10,组合模式(Composite Pattern)是将对象组合成树形结构以表示“部分–整体”的层次结 构。使得用户对单个对象和组合对象的使用具有一致性。

11,外观模式(Facade Pattern)是为子系统中的一组接口提供一个一致的界面,此模式定义 了一个高层接口,这个接口使得这一子系统更加容易使用。

12,享元模式(Flyweight Pattern)是以共享的方式高效的支持大量的细粒度的对象。

行为模式

13,模板方法模式(Template Method Pattern)使得子类可以不改变一个算法的结构即可重 定义该算法的某些特定步骤。

14,命令模式(Command Pattern)是将一个请求封装为一个对象,从而使你可用不同的请 求对客户端进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。

15,责任链模式(Chain of Responsibility Pattern),在该模式里,很多对象由每一个对象对其 下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理 此请求,这使得系统可以在不影响客户端的情况下动态地重新组织链和分配责任。

16,策略模式(Strategy Pattern)就是准备一组算法,并将每一个算法封装起来,使得它们 可以互换。

17,中介者模式(Mediator Pattern)就是定义一个中介对象来封装系列对象之间的交互。终 结者使各个对象不需要显示的相互调用 ,从而使其耦合性松散,而且可以独立的改变他们 之间的交互。

18,观察者模式(Observer Pattern)定义对象间的一种一对多的依赖关系,当一个对象的状 态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

19,备忘录模式(Memento Pattern)是在不破坏封装的前提下,捕获一个对象的内部状态, 并在该对象之外保存这个状态。

20,访问者模式(Visitor Pattern)就是表示一个作用于某对象结构中的各元素的操作,它使 你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

21,状态模式(State Pattern)就是对象的行为,依赖于它所处的状态。

22,解释器模式(Interpreter Pattern)就是描述了如何为简单的语言定义一个语法,如何在 该语言中表示一个句子,以及如何解释这些句子。

23,迭代器模式(Iterator Pattern)是提供了一种方法顺序来访问一个聚合对象中的各个元 素,而又不需要暴露该对象的内部表示。

设计模式这么多,怎么巧记哈

————————————————
原文链接:https://blog.csdn.net/wzgbgz/article/details/79276341

1,创建型模式有五种:工厂方法模式 、抽象工厂模式 、单例模式 、建造者模式 、原型模式
口诀:原来的建设工人单独抽奖
解释:原(原型模式)来的建(建造者模式)设工(工厂方法模式)人单(单例模式)独抽(抽象方法模式)奖。

2,结构型模式有七中:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式
口诀:带上适当的装备组合可以让外国侨胞享受(游戏)
解释:带(代理模式)上适(适配器模式)当的装(装饰模式)备组(组合模式)合可以让外(外观模式)国侨(桥接模式)胞享(享元模式)受(游戏)

3,行为型模式有十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式
口诀:多次命令和责备中,车模见状慌忙解开(衣服)
解释:多次(迭:多次的意思,迭代模式)命(命令模式)令和责(责任链模式)备(备忘录模式)中(中介者模式),车(策略模式)模(模板方法模式)见(观察着模式)状(状态模式)慌(访问者模式)忙解(解释器模式)开(衣服)。
————————————————
原文链接:https://blog.csdn.net/wzgbgz/article/details/79276341

设计模式的基本原则

最终目的:高内聚,低耦合

  1. 开放封闭原则 (OCP,Open For Extension, Closed For Modification Principle)
    类的改动是通过增加代码进行的,而不是修改源代码。
  2. 单一职责原则 (SRP,Single Responsibility Principle)
    类的职责要单一,对外只提供一种功能,而引起类变化的原因都应该只有一个。
  3. 依赖倒置原则(DIP,Dependence Inversion Principle)
    依赖于抽象(接口),不要依赖具体的实现(类),也就是针对接口编程。
  4. 接口隔离原则(ISP,Interface Segegation Principle)
    不应该强迫客户的程序依赖他们不需要的接口方法。一个接口应该只提供一种对外功能,
    不应该把所有操作都封装到一个接口中去。
  5. 里氏替换原则(LSP, Liskov Substitution Principle)
    任何抽象类出现的地方都可以用他的实现类进行替换。实际就是虚拟机制,语言级别实 现面向对象功能。
  6. 优先使用组合而不是继承原则(CARP,Composite/Aggregate Reuse Principle)
    如果使用继承,会导致父类的任何变换都可能影响到子类的行为。 如果使用对象组合,就降低了这种依赖关系。
  7. 迪米特法则(LOD,Law of Demeter)
    一个对象应当对其他对象尽可能少的了解,从而降低各个对象之间的耦合,提高系统的
    可维护性。例如在一个程序中,各个模块之间相互调用时,通常会提供一个统一的接口来实 现。这样其他模块不需要了解另外一个模块的内部实现细节,这样当一个模块内部的实现发 生改变时,不会影响其他模块的使用。(黑盒原理)
开闭原则案例

在这里插入图片描述

依赖倒置原则

在这里插入图片描述

迪米特法则
  1. 和陌生人说话
    在这里插入图片描述
  2. 不和陌生人说话在这里插入图片描述
  3. 与依赖倒转原则结核 某人和抽象陌生人说话,让某人与陌生人解耦合。
    在这里插入图片描述

创建型模式

单例模式

单例模式是一种对象创建型模式,使用单例模式,可以保证为一个类只生成唯一的实例 对象。也就是说,在整个程序空间中,该类只存在一个实例对象。
GoF 对单例模式的定义是:保证一个类、只有一个实例存在,同时提供能对该实例加以访问的全局访问方法。
在这里插入图片描述

为什么要使用单例

在应用系统开发中,我们常常有以下需求:

  • 在多个线程之间,比如初始化一次 socket 资源;比如 servlet 环境,共享同一个资源或者 操作同一个对象
  • 在整个程序空间使用全局变量,共享资源
  • 大规模系统中,为了性能的考虑,需要节省对象的创建时间等等。
    因为 Singleton 模式可以保证为一个类只生成唯一的实例对象,所以这些情况,Singleton 模 式就派上用场了。
实现单例的基本步骤
  1. 构造函数私有化
  2. 提供一个全局的静态方法(全局访问点)
  3. 在类中定义一个静态指针,指向本类的变量的静态变量指针
饿汉式单例和懒汉式单例
#include <iostream> using namespace std;
//懒汉式
class Singelton {
private:
	Singelton() {
		m_singer = NULL;
		m_count = 0;
		cout << "构造函数 Singelton ... do" << endl;
	}
public:
	static Singelton \*getInstance() {
		if (m_singer == NULL ) //懒汉式:1 每次获取实例都要判断 2 多线程会有问题 
		{
			m_singer = new Singelton; 
		}
		return m_singer; 
	}
	static void printT() {
		cout << "m\_count: " << m_count << endl; 
	}
private:
	static Singelton \*m_singer; static int m_count;
};

饿汉式

using namespace std;
class Singelton2 {
private:
    Singelton2() {
        m_singer = NULL;
        m_count = 0;
        cout << "构造函数 Singelton ... do" << endl;
    }
public:
    static Singelton2 \*getInstance() {
        if (m_singer == NULL ) {
            m_singer = new Singelton2; }
        return m_singer; }
    static void Singelton2::FreeInstance() {
        if (m_singer != NULL) {
            delete m_singer;
            m_singer = NULL;
            m_count = 0;
        }
    }
    static void printT() {
        cout << "m\_count: " << m_count << endl; }
private:
    static Singelton2 \*m_singer; static int m_count;
};

多线程下的懒汉式单例和饿汉式单例

多线程的情况下,饿汉式会存在线程安全的问题
如何解决这个问题?通常是采取加锁的方式进行处理

static Singleton \*Instantialize() {
if(pInstance == NULL) //double check 
{
	//加锁
	cs.Lock();
	if(pInstance==NULL){
		pInstance = new Singleton();
	}
	//释放锁
	cs.Unlock();
}
return pInstance; }

简单工厂模式

是什么

简单工厂模式属于类的创建型模式,又叫做静态工厂方法模式。通过专门定义一个类来负 责创建其他类的实例,被创建的实例通常都具有共同的父类。

  1. 工厂(Creator)角色 简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类可以被外界直接调
    用,创建所需的产品对象。
  2. 抽象(Product)角色
    简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
  3. 具体产品(Concrete Product)角色
    简单工厂模式所创建的具体实例对象
    在这里插入图片描述
  4. 在这个模式中,工厂类是整个模式的关键所在。它包含必要的判断逻辑,能够根据外界 给定的信息,决定究竟应该创建哪个具体类的对象。用户在使用时可以直接根据工厂类去创 建所需的实例,而无需了解这些对象是如何创建以及如何组织的。有利于整个软件体系结构 的优化。不难发现,简单工厂模式的缺点也正体现在其工厂类上,由于工厂类集中了所有实 例的创建逻辑,所以“高内聚”方面做的并不好。另外,当系统中的具体产品类不断增多时
class Fruit{
public:
    virtual~Fruit()=0;
    virtual void getFruit()=0;
};

class Banana:public Fruit{
public:
    void getFruit(){
        cout<<"香蕉"<<endl;
    }
};

class Pear:public Fruit{
    // Fruit interface
public:
    void getFruit(){
        cout<<"梨子"<<endl;
    }
};

//工厂不是一个抽象工厂
/\*\*
 \* @brief The Factory class
 \*/
class Factory{
    static Fruit\* Create(char \*name){
        Fruit \*fruit=NULL;
        if(strcmp(name,"pear")==0){
            fruit=new Pear;
        }else if(strcmp(name,"banana")==0){
            fruit=new Banana;
        }else{

        }

    }
};

工厂模式

工厂方法模式同样属于类的创建模式,又被成为多态工厂模式,工厂模式的意义是定义一个创建产品的工厂接口,将创建工作推迟到子类中
核心工厂类不再负责产品的创建,这样,核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,好处是,可以在不修改具体工厂角色的情况下引入新的产品

类图角色和职责

抽象工厂(Creator)角色
工厂方法模式的核心,任何工厂类都必须实现这个接口。

具体工厂( Concrete Creator)角色
具体工厂类是抽象工厂的一个实现,负责实例化产品对象。

抽象(Product)角色
工厂方法模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。

具体产品(Concrete Product)角色
工厂方法模式所创建的具体实例对象
在这里插入图片描述

在这里插入图片描述

工厂模式与简单工厂之比较

工厂方法类核心是一个抽象工厂,而简单工厂是放一个具体的工厂
抽象工厂需要扩展的时候,仅仅需要在添加新产品对象的时候,添加一个具体对象和具体对象的工厂即可,原有的工厂无需修改,符合开闭原则
如下代码,核心类由如下两个类组成,子类靠实现此两接口完成。

class Fruit{
public:
    virtual ~Fruit()=0;
};


class FruitFactory{
public:
    virtual ~FruitFactory()=0;
    virtual Fruit\* getFruit()=0;
};


抽象工厂模式

抽象工厂模式是所有形态的工厂模式中最为抽象和最其一般性的。抽象工厂模式可以向 客户端提供一个接口,使得客户端在不必指定产品的具体类型的情况下,能够创建多个产品 族的产品对象。

产品族和产品等级结构

在这里插入图片描述
在这里插入图片描述

模式中包含的角色与职责
  1. 抽象工厂(Creator)角色
    抽象工厂模式的核心,包含对多个产品结构的声明,任何工厂类都必须实现这个接口。
  2. 具体工厂( Concrete Creator)角色
    具体工厂类是抽象工厂的一个实现,负责实例化某个产品族中的产品对象。
  3. 抽象(Product)角色
    抽象模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
  4. 具体产品(Concrete Product)角色
    抽象模式所创建的具体实例对象

在这里插入图片描述

/\*\*
 \* 总结上来说:抽象工厂是一个大型工厂,其不仅仅可以生产某一种单一的产品
 \* 其是可以生产某一类产品,我们的抽象工厂的定义扩展为不同的类型的工厂生产
 \* 出不同工厂生产的产品
 \*/
class Fruit{
public:
    virtual ~Fruit()=0;
    virtual void sayname()=0;
};

class FruitFactory{
public:
    virtual Fruit\* getApple()=0;
    virtual Fruit\* getBanana()=0;
    virtual ~FruitFactory()=0;
};

class SouthBanana:public Fruit{
public:
    virtual void sayname() {
        cout<<"South Banana"<<endl;
    }
};

class SouthApple:public Fruit{
public:
    virtual void sayname(){
        cout<<"South Apple"<<endl;
    }
};

class NorthBanana:public Fruit{
public:
    virtual void sayname() {
        cout<<"North Banana"<<endl;
    }
};

class NorthApple:public Fruit{
public:
    void sayname(){
        cout<<"North Apple"<<endl;
    }
};

class SouthFruitFactory:public FruitFactory{
public:
    Fruit \*getApple(){
        return new SouthApple;
    }
    Fruit \*getBanana(){
        return new SouthBanana;
    }
};

class NorthFruitFactory:public FruitFactory{
public:
    Fruit \*getApple(){
        return new NorthApple;
    }
    Fruit \*getBanana(){
        return new NorthBanana;
    }
};


建造者模式

Builder 模式也叫建造者模式或者生成器模式,是由 GoF 提出的 23 种设计模式中的一种。 Builder 模式是一种对象创建型模式之一,用来隐藏复合对象的创建过程,它把复合对象的 创建过程加以抽象,通过子类继承和重载的方式,动态地创建具有复合属性的对象。

builder 模式是为对象的创建而设计的模式,创建的是一个复合对象,被创建的对象为一个具有简单复合属性的复合对象,关注对象创建的各部分,不同工厂对产品属性有不同的创建方法。

角色和职责

在这里插入图片描述

  1. Builder:为创建产品各个部分,统一抽象接口。
  2. ConcreteBuilder:具体的创建产品的各个部分,部分 A, 部分 B,部分 C。
  3. Director:构造一个使用 Builder 接口的对象。
  4. Product:表示被构造的复杂对象。
    ConcreteBuilder 创建该产品的内部表示并定义它的装配过程,包含定义组成部件的类, 包括将这些部件装配成最终产品的接口
创建者模式与工厂模式的区别

Factory 模式中:
1、有一个抽象的工厂。
2、实现一个具体的工厂—汽车工厂。
3、工厂生产汽车 A,得到汽车产品 A。
4、工厂生产汽车 B,得到汽车产品 B。
这样做,实现了购买者和生产线的隔离。强调的是结果。

Builder 模式:
1、引擎工厂生产引擎产品,得到汽车部件 A。
2、轮胎工厂生产轮子产品,得到汽车部件 B。
3、底盘工厂生产车身产品,得到汽车部件 C。
4、将这些部件放到一起,形成刚好能够组装成一辆汽车的整体。
5、将这个整体送到汽车组装工厂,得到一个汽车产品。

这样做,目的是为了实现复杂对象生产线和其部件的解耦。强调的是过程
两者的区别在于:
Factory 模式不考虑对象的组装过程,而直接生成一个我想要的对象。
Builder 模式先一个个的创建对象的每一个部件,再统一组装成一个对象。
Factory 模式所解决的问题是,工厂生产产品。
而 Builder 模式所解决的问题是工厂控制产品生成器组装各个部件的过程,然后从产品
生成器中得到产品。
Builder 模式不是很常用。模式本身就是一种思想。知道了就可以了。

案例

关键字:建公寓工程队 FlatBuild 别墅工程队 VillaBuild 设计者Director

class Builder {
public:
	virtual void makeFloor() = 0; virtual void makeWall() = 0; 
	virtual void makeDoor() = 0; virtual House \*GetHouse() = 0;
};

//公寓
class FlatBuild : public Builder {
//别墅
class VillaBuild : public Builder {

class Director {
public:
void Construct(Builder \*builder) {
	builder->makeFloor(); 
	builder->makeWall(); 
	builder->makeDoor();
}

//最终实现效果

//客户直接造房子
House \*pHose = new House; 
pHose->setDoor("wbm 门");
pHose->setFloor("wbmFloor"); 
pHose->setWall("wbmWall"); 
delete pHose;

//工程队直接造房子 
Builder \*builder = new FlatBuild; 
builder->makeFloor(); 
builder->makeWall(); 
builder->makeDoor();

//指挥者(设计师)指挥 工程队 和 建房子 
Director \*director = new Director;

//建公寓
Builder \*builder = new FlatBuild; 
director->Construct(builder); //设计师 指挥 工程队干活 
House \*house = builder->GetHouse();
cout << house->getFloor() << endl;
delete house;
delete builder;
builder = new VillaBuild;
director->Construct(builder); //设计师 指挥 工程队干活 
house = builder->GetHouse();
cout << house->getFloor() << endl;
delete house;
delete builder;
delete director;
system("pause");


由于工程队的基本操作已经被抽象成方法,所以工厂师在操作的时候,只需要调用对应接口的方法,从而达到给工程师某个类型的实例的时候,工程师可以按照对应类型的要求去实例化。

原型模式prototype

Prototype 是一种对象创建型模式,他采取复制原型对象的方法来创建对象的实例。使用Prototype模式创建的实例,具有与原型一样的数据。

  1. 由原型对象自身创建目标对象,也就是说,对象创建这一动作发自对象本身
  2. 目标对象是原型对象的一个克隆。也就是说,通过Prototype模式创建的对象,不仅仅与原型具有一样的结构,还具有一样的值。
  3. 根据对象克隆深度层次不同,有深度克隆和浅度克隆的区别
角色与职责

在这里插入图片描述

原型模式主要面对的问题是:“某些结构复杂的对象”的创建工作;由于需求的变化,这些对象经常面临着剧烈的变化,但是他们却拥有比较稳定一致的接口。
适用情况
一个复杂对象,具有自我复制功能,统一一套接口。

案例
class Person {
public:
virtual Person \*Clone() = 0; 
virtual void printT() = 0;
};

class JavaProgrammer : public Person {
public:
virtual Person \*Clone() {
	JavaProgrammer \*p = new JavaProgrammer;
	 \*p = \*this;
	 return p; 
}

结构型模式

代理模式

Proxy 模式又叫做代理模式,是构造型的设计模式之一,它可以为其他对象提供一 种代理(Proxy)以控制对这个对象的访问。
所谓代理,是指具有与代理元(被代理的对象)具有相同的接口的类,客户端必须 通过代理与被代理的目标类交互,而代理一般在交互的过程中(交互前后),进行某些 特别的处理。

类图角色和职责

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  • subject(抽象主题角色):
    真实主题与代理主题的共同接口。
  • RealSubject(真实主题角色):
    定义了代理角色所代表的真实对象。
  • Proxy(代理主题角色):
    含有对真实主题角色的引用,代理角色通常在将客户端调用传递给真是主题对象之前或
    者之后执行某些操作,而不是单纯返回真实的对象。

适合于:
为其他对象提供一种代理以控制对这个对象的访问。

案例
using namespace std;

class Interface{
public:
    virtual void Request()=0;
};

class RealClass:public Interface{
public:
    virtual void Request() {
        cout<<"真是的请求"<<endl;
    }
};

class ProxyClass:public Interface{
    PointerPropertyBuilderByName(RealClass,realClass,private)
    //在该代理类中代理其他对象
    virtual void Request() {
        m_realClass=new RealClass();
        cout<<"before call"<<endl;
        m_realClass->Request();
        cout<<"after call"<<endl;
        delete m_realClass;
    }
};

装饰模式

装饰模式又称包装模式,通过一种对客户端透明的方式来扩展对象,是继承关系的一个替换方案

角色与职责

在这里插入图片描述

适用于:
装饰者模式(Decorator Pattern)动态的给一个对象添加一些额外的职责。就增加功能 来说,此模式比生成子类更为灵活。

案例
class Car{
public:
    virtual void show()=0;
};

class RunCar:public Car{
public:
    void run() {
        cout << "可以跑" << endl;
    }
    void show(){
        run();
    }
};

class SwimCarDirector : public Car {
    PointerPropertyBuilderByName(Car,car,private)
public:
    //这里送入被包装对象是关键
    SwimCarDirector(Car \*p){
        this->m_car=p;
    }
    void swim(){
        cout<<"可以游泳"<<endl;
    }

    // Car interface
public:
    void show(){
        //使用他人的功能
        this->m_car->show();
        //调用自己的功能。
        this->swim();
    }
};

class FlyCar:public Car{
    PointerPropertyBuilderByName(Car,car,private)
public:
    FlyCar(Car \*p){
        this->m_car=p;
    }
    void fly(){
        cout<<"可以飞"<<endl;
    }

    // Car interface
public:
    void show(){
        this->m_car->show();
        this->fly();
    }
};

案例
   ProxyClass \*pc = new ProxyClass;
    pc->Request();

    Car \*runcar = NULL;
    runcar = new RunCar;
    runcar->show();

    //开始包装
    SwimCarDirector \*scd = new SwimCarDirector(runcar);
    scd->show();

适配器模式

Adaptor模式也叫适配器模式,是构造型模式之一,通过Adapator模式可以改变类的对外部暴露接口

角色与职责

在这里插入图片描述

适用于: 是将一个类的接口转换成客户希望的另外一个接口。使得原本由于接口不兼容而不能
一起工作的那些类可以一起工作。

案例

//这个应该是目标接口吧
class Current18v{
public:
    void use18vCurrent(){
        cout<<"使用18v电压"<<endl;
    }
};

class Current220v{
public:
    void use220vCurrent(){
        cout<<"使用220v电压"<<endl;
    }
};

//继承目标接口
class Adapter:public Current18v{
PointerPropertyBuilderByName(Current220v,p220v,private)
public:
    Adapter(Current220v \*p220v){
        this->m_p220v=p220v;
    }
    void use18vCurrent(){
        cout<<"adapter 中使用电流"<<endl;
        m_p220v->use220vCurrent();
    }
};


组合模式

角色和职责

Composite 模式也叫组合模式,是构造型的设计模式之一。通过递归手段来构造树形的 对象结构,并可以通过一个对象来访问整个对象树。
在这里插入图片描述

Component (树形结构的节点抽象)

  • 为所有的对象定义统一的接口(公共属性,行为等的定义) - 提供管理子节点对象的接口方法
  • [可选]提供管理父节点对象的接口方法

Leaf (树形结构的叶节点) Component 的实现子类

Composite(树形结构的枝节点) Component 的实现子类

案例

class IFile{
public:
    virtual ~IFile()=0;
    virtual void display()=0;
    virtual int add(IFile\* file)=0;
    virtual int remove(IFile\* file)=0;
    virtual list<IFile\*>\* getChild()=0;
};

class File:public IFile{
    PointerPropertyBuilderByName(list<IFile\*>,list,private)
    PropertyBuilderByName(string,name,private)
public:
    File(string name){
        //文件是不允许有list的
        this->m_list=NULL;
        this->m_name=name;
    }
    ~File(){
        if(this->m_list!=NULL){
            delete m_list;
        }
    }
    virtual void display() {
        cout<<this->m_name<<endl;
    }
    virtual int add(IFile \*file){
        return -1;
    }
    int remove(IFile \*file){
        return -1;
    }
    list<IFile \*> \*getChild(){
        return NULL;
    }
};

class Directory:public IFile{
    PointerPropertyBuilderByName(list<IFile\*>,list,private)
    PropertyBuilderByName(string,name,private)
public:
    Directory(string name){
        this->m_name=name;
        this->m_list=new list<IFile\*>;
    }
    ~Directory(){
        if(m_list!=NULL){
            delete this->m_list;
            this->m_list=NULL;
        }

    }
    void display(){
        cout<<this->m_name;
    }
    int add(IFile \*file){
        this->m_list->push\_back(file);
        return 0;
    }
    int remove(IFile \*file){
        this->m_list->remove(file);
        return 0;
    }
    list<IFile \*> \*getChild(){
        return this->m_list;
    }
};

桥接模式

概念

Bridge 模式又叫做桥接模式,是构造型的设计模式之一。Bridge 模式基于类的最小设计 原则,通过使用封装,聚合以及继承等行为来让不同的类承担不同的责任。它的主要特点是 把抽象(abstraction)与行为实现(implementation)分离开来,从而可以保持各部分的独 立性以及应对它们的功能扩展。

角色与职责

在这里插入图片描述

  1. Client
    Bridge 模式的使用者
  2. Abstraction
    抽象类接口(接口或抽象类)维护对行为实现(Implementor)的引用
  3. Refined Abstraction
    Abstraction 子类
  4. Implementor
    行为实现类接口 (Abstraction 接口定义了基于
  5. Implementor 接口的更高层次的操作)
    ConcreteImplementor Implementor 子类

适用于:
桥接模式(Bridge Pattern)是将抽象部分与实现部分分离(解耦合),使它们都可以独立的变化。

安装 发动机 ;不同型号的车,安装不同型号的发动机
图形 填 颜色 不同形状的图形,填充上 不同的颜色

将“车 安装 发动机”这个抽象 和 实现进行分离;两个名字 就设计两个类;
将“图形 填 颜色”这个抽象 和 实现 进行分离,两个名字,就设计两个类

案例
//引擎
class Engine{
public:
    virtual ~Engine();
    virtual void install()=0;
};
Engine::~Engine(){
}
//引擎

//4000引擎
class Engine4000:public Engine{
    public:
    void install(){
        cout<<"发动机4000安装"<<endl;
    }
};
//4000引擎

//3500 引擎
class Engine3500:public Engine{
    public:
    void install(){
        cout<<"发动机4000安装"<<endl;
    }
};
//3500引擎

//抽象汽车,维护抽象引擎
class Car{
PointerPropertyBuilderByName(Engine,engine,protected)
public:
    Car(Engine\* engine);
    virtual ~Car();
    virtual void installEngine()=0;
};
Car::Car(Engine \*engine){
    this->m_engine=engine;
}
Car::~Car(){

}
//抽象汽车

//实际汽车,维护抽象引擎,实际引擎由外部引入
class BMW7:public Car{
public:
    BMW7(Engine \*e);
public:
    void installEngine();
};

BMW7::BMW7(Engine \*e):Car(e){
}

void BMW7::installEngine(){
    cout<<"Bmw7:";
    m_engine->install();
}

外观模式

概念

Facade模式也叫做外观模式,Facade 模式为一 组具有类似功能的类群,比如类库,子系统等等,提供一个一致的简单的界面。这个一致的 简单的界面被称作 facade。

角色与职责

在这里插入图片描述

Façade
为调用方, 定义简单的调用接口。
Clients
调用者。通过 Facade 接口调用提供某功能的内部类群。
Packages
功能提供者。指提供功能的类群(模块或子系统)

适用于: 为子系统中统一一套接口,让子系统更加容易使用。

案例
class SystemA{
public:
    void doThing(){
        cout<<"System A do..."<<endl;
    }
};

class SystemB{
public:
    void doThing(){
        cout<<"System B do..."<<endl;
    }
};

class SystemC{
public:
    void doThing(){
        cout<<"System C do..."<<endl;
    }
};

class Facade{
    PointerPropertyBuilderByName(SystemA,a,private)
    PointerPropertyBuilderByName(SystemB,b,private)
    PointerPropertyBuilderByName(SystemC,c,private)
public:
    Facade(){
        m_a=new SystemA;
        m_b=new SystemB;
        m_c=new SystemC;
    }
    ~Facade(){
        delete  m_a;
        delete  m_b;
        delete  m_c;
    }
    void doThing(){
        m_a->doThing();
        m_b->doThing();
        m_c->doThing();
    }
};

享元模式 flyweight

概念

Flyweight模式也叫做享元模式,是构造型模式之一,它通过与其他类似对象共享数据减少内存占用。
其实作为Java程序员的我们,怎么理解这个模式,就是数据库连接池,一个池里面保留着一堆链接,使用到的时候,拿对应的出来用,避免资源的浪费。

角色与概念

在这里插入图片描述

  1. 抽象享元角色(Flyweight):
    所有具体享元类的父类,规定一些需要实现的公共接口。
  2. 具体享元角色(ConcreteFlyweight|UnshareConcreteFlyweight):
    抽象享元角色的具体实现类,并实现了抽象享元角色规定的方法。
  3. 享元工厂角色(FlyweightFactory):
    负责创建和管理享元角色。可以想象是数据库连接池。

使用场景: 是以共享的方式,高效的支持大量的细粒度的对象。
说白了就是拿一个容器存一堆对象,并且按照id获取对应对象,避免对象的重复创建

案例
using namespace std;

class Person{
    PropertyBuilderByName(string,name,protected)
    PropertyBuilderByName(int,age,protected)
    PropertyBuilderByName(int,sex,protected)
public:
    Person(string name,int age,int sex):m\_name(name),m\_age(age),m\_sex(sex){

    }
};

class Teacher:public Person{
    PropertyBuilderByName(string,id,private)
public:
    Teacher(string id,string name,int age,int sex):Person(name,age,sex){
        this->m_id=id;
    }
    void printT(){
        cout<<"id:"<<m_id<<"\t"
                <<"name:"<<m_name<<"\t"
                <<"age:"<<m_age<<"\t"
                <<"sex:"<<m_sex<<"\t"
           <<endl;
    }
};

class TeacherFactory{
private:
    map<string,Teacher\*> m_tpool;
public:
    TeacherFactory(){
        m_tpool.empty();
    }
    ~TeacherFactory(){
        while (!m_tpool.empty()) {
            //因为老师是在此容器里面创建的,所以需要在容器里面进行销毁
            Teacher\* tmp=NULL;
            map<string,Teacher\*>::const_iterator it = m_tpool.begin();
            tmp=it->second;
            m_tpool.erase(it);
            delete tmp;
        }
    }
    /\*\*
 \* @brief getTeachar 获取老师,如果数据库已经存在了,就没有必要再次创建
 \* @param name
 \* @param age
 \* @param sex
 \* @return
 \*/
    Teacher\* getTeachar(string name,int age,int sex){
        stringstream ss;
        ss<<name;
        ss<<age;
        ss<<sex;
        string tmp;
        ss>>tmp;
        map<string,Teacher\*>::iterator it = m_tpool.find(tmp);
        if(it!=m_tpool.end()){
            return it->second;
        }else{
            Teacher \*t = new Teacher(tmp,name,age,sex);
            m_tpool.insert(pair<string,Teacher\*>(tmp,t));
        }
    }
};

行为型模式

模板模式(Template)

Template Method模式也叫做模板方法模式,是行为模式之一,他把具有特定步骤算法中的某些必要的处理委托让给抽象方法,通过子类继承对抽象方法的不同实现改变整个算法的行为。

应用场景

Template Method 模式一般应用在具有以下条件的应用中:

  • 具有统一的操作步骤和操作过程
  • 具有不同的操作细节‘
  • 存在多个同样的操作步骤的应用场景,但某些具体 操作细节却各不相同

总结:
在抽象类中统一操作步骤,并规定好接口,让子类去实现接口,这样可以把每个具体子类和操作步骤耦合

角色与职责

在这里插入图片描述

  1. AbstractClass
    抽象类的父类
  2. ConcreteClass
    具体的实现子类
  3. templateMethod():
    模板方法
  4. method1()与 method2():
    具体步骤方法
案例
class MakeCar{
public:
    virtual ~MakeCar(){
    }
    virtual void makeHead()=0;
    virtual void makeBody()=0;
    virtual void makeTail()=0;
public:
    void make(){
        //一些统一的操作步骤
        makeHead();
        makeBody();
        makeTail();
    }
};

class Bus:public MakeCar{
public:
    void makeHead(){
        cout<<"bus make head"<<endl;
    }
    void makeBody(){
        cout<<"bus make body"<<endl;
    }
    void makeTail(){
        cout<<"bus make tail"<<endl;
    }
};

class Jeep:public MakeCar{

public:
    void makeHead(){
        cout<<"jeep make head"<<endl;
    }
    void makeBody(){
        cout<<"jeep make body"<<endl;
    }
    void makeTail(){
        cout<<"jeep make tail"<<endl;
    }
};

命令模式

概念模式

Command 模式也叫命令模式,是行为设计模式的一种,Command 模式通过被称为 Command 的类封装了对目标对象的调用行为以及调用参数。

在面向对象的程序设计中,一个对象调用另一个对象,一般情况下的调用过程是:创建 目标对象实例;设置调用参数;调用目标对象的方法。

但在有些情况下有必要使用一个专门的类对这种调用过程加以封装,我们把这种专门 的类称作 command 类。

整个调用过程比较繁杂,或者存在多处这种调用。这时,使用 Command 类对该调用加 以封装,便于功能的再利用。-

调用前后需要对调用参数进行某些处理。调用前后需要进行某些额外处理,比如日志, 缓存,记录历史操作等。

角色与职责

在这里插入图片描述

  1. Command
    Command 命令的抽象类。
  2. ConcreteCommand
    Command 的具体实现类。
  3. Receiver
    需要被调用的目标对象。
  4. Invorker
    通过 Invorker 执行 Command 对象。

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

akeBody(){
cout<<“bus make body”<<endl;
}
void makeTail(){
cout<<“bus make tail”<<endl;
}
};

class Jeep:public MakeCar{

public:
void makeHead(){
cout<<“jeep make head”<<endl;
}
void makeBody(){
cout<<“jeep make body”<<endl;
}
void makeTail(){
cout<<“jeep make tail”<<endl;
}
};


### 命令模式


#### 概念模式


Command 模式也叫命令模式,是行为设计模式的一种,Command 模式通过被称为 Command 的类封装了对目标对象的调用行为以及调用参数。


在面向对象的程序设计中,一个对象调用另一个对象,一般情况下的调用过程是:创建 目标对象实例;设置调用参数;调用目标对象的方法。


但在有些情况下有必要使用一个专门的类对这种调用过程加以封装,我们把这种专门 的类称作 command 类。


整个调用过程比较繁杂,或者存在多处这种调用。这时,使用 Command 类对该调用加 以封装,便于功能的再利用。-


调用前后需要对调用参数进行某些处理。调用前后需要进行某些额外处理,比如日志, 缓存,记录历史操作等。


#### 角色与职责


![在这里插入图片描述](https://img-blog.csdnimg.cn/20191122150329987.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2JsdWVib3o=,size_16,color_FFFFFF,t_70)


1. Command  
 Command 命令的抽象类。
2. ConcreteCommand  
 Command 的具体实现类。
3. Receiver  
 需要被调用的目标对象。
4. Invorker  
 通过 Invorker 执行 Command 对象。




[外链图片转存中...(img-6ocYg3ES-1714986845347)]
[外链图片转存中...(img-YKOoTYVx-1714986845348)]

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化的资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618608311)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

  • 26
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值