设计模式 ---- 适配器模式&桥梁模式&代理模式

适配器模式

适配器模式和装饰器模式在代码结构上有一些相似之处,都可能通过继承目标接口,并持有另一个对象来完成包装(将新的接口翻译为业务逻辑能够理解的老接口)

装饰器模式是为了在不改变原有接口的情况下,为对象增加新的职责或功(接口基本不变,增加职责)

适配器模式则是为了让原本接口不兼容的对象能够被现有代码使用,将一个已有接口转换成客户端所需要的接口(功能目的通常不变,改变接口),这样不需要重写新的方法

比如现有游戏数据保存类:

class Save{

public:

	virtual void uploadData(int userID) = 0;

}


class SaveData : public Save{

public:

	void uploadData(int userID) override{
		
		std::cout << "原版本地保存数据" << std::endl;
		
	}
}

现在厂商觉得本地保存数据不安全,引进了云存储

class CloudUpload{
	
public:

	void cluodUploadFun(int id){

		std::cout << "这是云服务存储的接口,用户ID: " << id << std::endl;
		
	}
}

那么为了然云存储适配现有接口就可以有适配器


class cloudUploadAdapter : public Save{

private:

	CloudUpload* cloudUpload;

public:
	
	cloudUploadAdapter(CloudeUpload* cloud) : cloudUpload(cloud){}
	
	void uploadData(int userID){
		
		std::cout << "这是适配器模式接口" << std::endl;
		
		cloudUpload -> cludUploadFun();
	}

}

这样在主业务种就有


CloudUpload cloudUploadIns;

cloudUploadAdapter adapter(&cloudUploadIns);

adapter.uploadData(123456);

这样将cloudUploadIns.cludUploadFun()变成了我们熟悉的adapter.uploadDate(123456)

从客户端的角度来看,它根本不需要知道 CloudeUpload 的存在。客户端仍然按照原来的 Save 接口调用 uploadData(),而适配器负责在内部将这个调用转换成云存储所提供的接口。

所以适配器的核心就是:让一个原本接口不兼容的对象,能够以客户端熟悉的接口被使用。

桥梁模式

了解桥梁模式的要点是"组合”,比如现有一个类,实际现有的作用其实是有两种类型组合起来的,比如

//铁狗牌
class IronIDTag{

private:

	int tagID;

	std::string IDTagMaterial = "iron";

public:

	IDInfoTag(int ID): tagID(ID){}

	void ShowInfo(){

		//Play voice messages for strangers and so on...

	}
}

// 著恶化号的成品类
class ChineseRuralDog{

private:

	std::string name;

	IronIDTag idTag;

pubilc:
	ChineseRuralDog(int ID):idTag(ID){}
	
	viod ShowInfoForStranger(){
		idTag.ShowInfo();
	}

}

在主业务种

ChineseRuralDog myDog(12);

myDog.ShowInfoForStranger();

但是如果我需要增加dog的种类和不同材质的身份牌呢,按照上面的写法,dog和IDtag其实是高度耦合的,为了降低耦合度,可以将两个类分别,抽象出来,然后通过dog 拥有身份牌 来进行桥接

//狗牌基类
class IDTag{

private:


	std::string IDTagMaterial;

	virtiual void ShowInfo() = 0;

};

//狗的基类
class Dog{

private:

	std::string name;

	IDTag* tag;

public;

	Dog(std::string name, IDTag* tag)
        : name(name), tag(tag)
    {
    }

	virtual void ShowInfoForStranger() = 0;

}


在具体使用的时候

class IronIDTag : public IDTag
{
public:
    void ShowInfo() override
    {
        std::cout << "这是铁制狗牌" << std::endl;
    }
};


class ChineseRuralDog : public Dog
{
public:
    ChineseRuralDog(std::string name, IDTag* tag)
        : Dog(name, tag)
    {
    }

    void ShowInfoForStranger() override
    {
        std::cout << "我是中华田园犬:" << name << std::endl;
        tag->ShowInfo();
    }
};

```C++
IronIDTag ironTag;

ChineseRuralDog dog("大黄", &ironTag);

dog.ShowInfoForStranger();

后期如果需要增加狗的种类,和身份牌的种类就不需要增加对应的牌和狗的具体类就好,而不需要写多个已经组合号的成品类

桥梁模式解决的不是“两个对象需要组合”这么简单,而是当一个类中存在两个或者多个独立变化的维度时,将这些维度拆分成独立的继承体系,再通过组合将它们连接起来,从而避免随着两个维度的组合产生大量子类

代理模式

代理模式:为真实对象提供一个代理对象,客户端不直接访问真实对象,而是通过代理对象间接访问真实对象,由代理对象控制或增强对真实对象的访问

和适配器模式的解决问题不一样,适配器模式只是将不同的接口翻译成现有的接口,从而达到不修改老代码的目的,代理模式是控制客户端(即调用代理的逻辑)对实际对象的访问权限,是否可以访问,如何访问,访问哪些内容...,也可以理解为,代理其实就是一个伪装成实际对象的中间层,客户端想要访问对象,其实访问的是一个伪装成对象的代理

及比如你想找明星要签名

你实际找到的是 经纪人,经纪人确定你是否是黑粉,在找到明星本人拿到签名,经纪人 在将签名给你(当然这里排除特殊情况,例如直接叨扰他人线下直接找人)

例子加载图片,现在已知加载图片需要很长时间,不希望每次显示图片都去加载一遍

class Image
{
public:

    Image()
    {
        loadImg();
    }

    void Display()
    {
        cout << "显示图片" << endl;
    }

private:

    void loadImg()
    {
        cout << "加载图片" << endl;
    }
};

直接访问

Image image;
image.Display();

如果图片太大,每次有需求都要经过这些步骤就太慢了

增加一个代理

class Image
{
public:
    virtual void Display() = 0;
};

class RealImage : public Image
{

public:

	Image()
    {
        LoadImage();
    }

    void Display() override
    {
        cout << "显示图片" << endl;
    }

private:

    void LoadImage()
    {
        cout << "加载图片" << endl;
    }
};

class ImageProxy : public Image
{
private:

    RealImage* image = nullptr;

public:

    void Display() override
    {
        if (image == nullptr)
        {
            image = new RealImage();
        }

        image->Display();
    }
};

有可能会有人问,直接在主程序里写要给if判断就好了啊,没必要增加一个代理,这和普通的装饰者模式有什么区别

这是因为,装饰者模式是对象没有的功能,将需要的功能一层层加上去,代理模式是将现象有的功能剥离出来,使功能详细过程对其透明(看不见)

如果你后续想要对display加上其他操作,为了不修改主程序,可以直在代理种操作,客户端不关心

但是如果使用装饰者,需要修改主程序(代理模式有点像简单工厂--生产 )(代理模式 -- 封装透明)(装饰者 -- 加功能)

posted on 2026-09-06 14:00  咸云闲鱼  阅读(4)  评论(0)    收藏  举报