设计模式——单一职责模式之桥模式

简介: 在软件组件的设计中,如果责任划分的不清晰,使用继承得到的结果往往是随着需求的变化,子类急剧膨胀,同时充斥着重复代码,这时候的关键是划清责任。

前言



一、“单一职责” 模式


在软件组件的设计中,如果责任划分的不清晰,使用继承得到的结果往往是随着需求的变化,子类急剧膨胀,同时充斥着重复代码,这时候的关键是划清责任。

典型模式

Decorator

Bridge


二、Bridge 桥模式



1、动机


由于某些类型的固有的实现逻辑,使得它们具有两个变化的维度,乃至多个纬度的变化。

如何应对这种“多维度的变化”?如何利用面向对象技术来使得类型可以轻松地沿着两个乃至多个方向变化,而不引入额外的复杂度?


2、模式定义


将抽象部分(业务功能)与实现部分(平台实现)分离,使它们都可以独立地变化。


3、伪代码示例


bridge1.cpp

//bridge1.cpp
class Messager{
public:
    virtual void Login(string username, string password)=0;
    virtual void SendMessage(string message)=0;
    virtual void SendPicture(Image image)=0;
    virtual void PlaySound()=0;
    virtual void DrawShape()=0;
    virtual void WriteText()=0;
    virtual void Connect()=0;
    virtual ~Messager(){}
};
//平台实现 n
//类的数目:1 + n + m * n
class PCMessagerBase : public Messager{
public:
    virtual void PlaySound(){
        //**********
    }
    virtual void DrawShape(){
        //**********
    }
    virtual void WriteText(){
        //**********
    }
    virtual void Connect(){
        //**********
    }
};
class MobileMessagerBase : public Messager{
public:
    virtual void PlaySound(){
        //==========
    }
    virtual void DrawShape(){
        //==========
    }
    virtual void WriteText(){
        //==========
    }
    virtual void Connect(){
        //==========
    }
};
//业务抽象 
class PCMessagerLite : public PCMessagerBase {
public:
    virtual void Login(string username, string password){
        PCMessagerBase::Connect();
        //........
    }
    virtual void SendMessage(string message){
        PCMessagerBase::WriteText();
        //........
    }
    virtual void SendPicture(Image image){
        PCMessagerBase::DrawShape();
        //........
    }
};
class PCMessagerPerfect : public PCMessagerBase {
public:
    virtual void Login(string username, string password){
        PCMessagerBase::PlaySound();
        //********
        PCMessagerBase::Connect();
        //........
    }
    virtual void SendMessage(string message){
        PCMessagerBase::PlaySound();
        //********
        PCMessagerBase::WriteText();
        //........
    }
    virtual void SendPicture(Image image){
        PCMessagerBase::PlaySound();
        //********
        PCMessagerBase::DrawShape();
        //........
    }
};
class MobileMessagerLite : public MobileMessagerBase {
public:
    virtual void Login(string username, string password){
        MobileMessagerBase::Connect();
        //........
    }
    virtual void SendMessage(string message){
        MobileMessagerBase::WriteText();
        //........
    }
    virtual void SendPicture(Image image){
        MobileMessagerBase::DrawShape();
        //........
    }
};
class MobileMessagerPerfect : public MobileMessagerBase {
public:
    virtual void Login(string username, string password){
        MobileMessagerBase::PlaySound();
        //********
        MobileMessagerBase::Connect();
        //........
    }
    virtual void SendMessage(string message){
        MobileMessagerBase::PlaySound();
        //********
        MobileMessagerBase::WriteText();
        //........
    }
    virtual void SendPicture(Image image){
        MobileMessagerBase::PlaySound();
        //********
        MobileMessagerBase::DrawShape();
        //........
    }
};
void Process(){
    //编译时装配
    Messager *m = new MobileMessagerPerfect();
}

基于装饰模式的经验,将业务的继承修改为组合,进行如下的修改:

class Messager{
public:
    //存在着多个变化的维度:平台实现 + 业务抽象
    virtual void Login(string username, string password)=0;
    virtual void SendMessage(string message)=0;
    virtual void SendPicture(Image image)=0;
    virtual void PlaySound()=0;
    virtual void DrawShape()=0;
    virtual void WriteText()=0;
    virtual void Connect()=0;
    virtual ~Messager(){}
};
//平台实现 n
//类的数目:1 + n + m * n
//主要到这个类里只实现了Messager这个类的部分接口
class PCMessagerBase : public Messager{
public:
    virtual void PlaySound(){
        //**********
    }
    virtual void DrawShape(){
        //**********
    }
    virtual void WriteText(){
        //**********
    }
    virtual void Connect(){
        //**********
    }
};
class MobileMessagerBase : public Messager{
public:
    virtual void PlaySound(){
        //==========
    }
    virtual void DrawShape(){
        //==========
    }
    virtual void WriteText(){
        //==========
    }
    virtual void Connect(){
        //==========
    }
};
//业务抽象 
//主要到这个类里只需要实现了Messager这个类的部分接口,如果继承Messager是不合适的
class MessagerLite {
    Messager* messager; //指针才具有多态性
public:
    virtual void Login(string username, string password){
        messager->Connect();
        //........
    }
    virtual void SendMessage(string message){
        messager->WriteText();
        //........
    }
    virtual void SendPicture(Image image){
        messager->DrawShape();
        //........
    }
};
class MessagerPerfect {
    Messager* messager;
public:
    virtual void Login(string username, string password){
        messager->PlaySound();
        //********
        messager->Connect();
        //........
    }
    virtual void SendMessage(string message){
        messager->PlaySound();
        //********
        messager->WriteText();
        //........
    }
    virtual void SendPicture(Image image){
        messager->PlaySound();
        //********
        messager->DrawShape();
        //........
    }
};
void Process(){
    //编译时装配
    Messager *m = new MobileMessagerPerfect();
}

PCMessageBase 类和 MessagerLite、MessagerPerfect 类都各自只实现了 Messager 的部分接口,说明 Messager 中的两部分的接口不应该放到一起,应该进行拆分:

bridge2.cpp

//bridge2.cpp
class Messager{
protected:
     MessagerImp* messagerImp;// MessagerImp
public:
    Messager(MessagerImpl* mimp) : messagerImpl(mimp) { }
    virtual void Login(string username, string password)=0;
    virtual void SendMessage(string message)=0;
    virtual void SendPicture(Image image)=0;
    virtual ~Messager(){}
};
class MessagerImp{
public:
    virtual void PlaySound()=0;
    virtual void DrawShape()=0;
    virtual void WriteText()=0;
    virtual void Connect()=0;
    virtual ~MessagerImp(){}
};
//平台实现 n
class PCMessagerImp : public MessagerImp{
public:
    virtual void PlaySound(){
        //**********
    }
    virtual void DrawShape(){
        //**********
    }
    virtual void WriteText(){
        //**********
    }
    virtual void Connect(){
        //**********
    }
};
class MobileMessagerImp : public MessagerImp{
public:
    virtual void PlaySound(){
        //==========
    }
    virtual void DrawShape(){
        //==========
    }
    virtual void WriteText(){
        //==========
    }
    virtual void Connect(){
        //==========
    }
};
//业务抽象 m
//类的数目:1+n+m
class MessagerLite : public Messager {
public:
    MessagerLite(MessagerImp* mimp) : Messager(mimp) { 
    }
    virtual void Login(string username, string password){
        messagerImp->Connect(); //messagerImpl字段在父类中声明了
        //........
    }
    virtual void SendMessage(string message){
        messagerImp->WriteText();
        //........
    }
    virtual void SendPicture(Image image){
        messagerImp->DrawShape();
        //........
    }
};
class MessagerPerfect  :public Messager {
public: 
    MessagerPerfect(MessagerImp* mimp) : Messager(mimp) { 
    }
    virtual void Login(string username, string password){
        messagerImp->PlaySound();
        //********
        messagerImp->Connect();
        //........
    }
    virtual void SendMessage(string message){
        messagerImp->PlaySound();
        //********
        messagerImp->WriteText();
        //........
    }
    virtual void SendPicture(Image image){
        messagerImp->PlaySound();
        //********
        messagerImp->DrawShape();
        //........
    }
};
void Process(){
    //运行时装配
    MessagerImp* mImp = new PCMessagerImp();
    Messager *m = new MessagerPerfect(mImp);
}


4、结构


【注】:

Abstraction -> Messgaer (稳定) 【imp对应到代码中就是 Messager 中有一个MessagerImpl类型的指针变量】

Implementor -> MessagerImpl (稳定)

RefinedAbstraction -> MessagerLite / MessagerPerfect (变化)

ConcreteImplementorX -> XXMessagerImpl (变化)

两个方向独立变化,而不是杂糅在一起。


总结


Bridge 模式使用“对象间的组合关系”解耦了抽象和实现之间固有的绑定关系,使得抽象和实现可以沿着各自的维度来变化。所谓抽象和实现沿着各自纬度的变化,即“子类化”它们。

Bridge 模式有时候类似于多继承方案,但是多继承方案往往违背单一职责原则(即一个类只有一个变化的原因),复用性比较差。Bridge 模式是比多继承方案更好的解决方法。

Bridge 模式的应用一般在“两个非常强的变化维度”,有时一个类也有多于两个的变化维度,这时可以使用 Bridge的扩展模式。


目录
相关文章
|
2月前
|
设计模式 前端开发 搜索推荐
前端必须掌握的设计模式——模板模式
模板模式(Template Pattern)是一种行为型设计模式,父类定义固定流程和步骤顺序,子类通过继承并重写特定方法实现具体步骤。适用于具有固定结构或流程的场景,如组装汽车、包装礼物等。举例来说,公司年会节目征集时,蜘蛛侠定义了歌曲的四个步骤:前奏、主歌、副歌、结尾。金刚狼和绿巨人根据此模板设计各自的表演内容。通过抽象类定义通用逻辑,子类实现个性化行为,从而减少重复代码。模板模式还支持钩子方法,允许跳过某些步骤,增加灵活性。
137 11
|
3月前
|
设计模式 安全 Java
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
|
24天前
|
设计模式
「全网最细 + 实战源码案例」设计模式——模式扩展(配置工厂)
该设计通过配置文件和反射机制动态选择具体工厂,减少硬编码依赖,提升系统灵活性和扩展性。配置文件解耦、反射创建对象,新增产品族无需修改客户端代码。示例中,`CoffeeFactory`类加载配置文件并使用反射生成咖啡对象,客户端调用时只需指定名称即可获取对应产品实例。
86 40
|
25天前
|
设计模式 关系型数据库
「全网最细 + 实战源码案例」设计模式——简单工厂模式
简单工厂模式是一种创建型设计模式,通过工厂类根据传入参数创建不同类型的对象,也称“静态工厂方法”模式。其结构包括工厂类、产品接口和具体产品类。优点是封装性强、代码复用性好;缺点是扩展性差,增加新产品时需修改工厂类代码,违反开闭原则。适用于对象种类较少且调用者无需关心创建细节的场景。
53 19
|
23天前
|
设计模式 Java
「全网最细 + 实战源码案例」设计模式——生成器模式
生成器模式(Builder Pattern)是一种创建型设计模式,用于分步骤构建复杂对象。它允许用户通过控制对象构造的过程,定制对象的组成部分,而无需直接实例化细节。该模式特别适合构建具有多种配置的复杂对象。其结构包括抽象建造者、具体建造者、指挥者和产品角色。适用于需要创建复杂对象且对象由多个部分组成、构造过程需对外隐藏或分离表示与构造的场景。优点在于更好的控制、代码复用和解耦性;缺点是增加复杂性和不适合简单对象。实现时需定义建造者接口、具体建造者类、指挥者类及产品类。链式调用是常见应用方式之一。
50 12
|
25天前
|
设计模式 关系型数据库
「全网最细 + 实战源码案例」设计模式——工厂方法模式
简单工厂模式是一种创建型设计模式,通过一个工厂类根据传入参数创建不同类型的产品对象,也称“静态工厂方法”模式。其结构包括工厂类、产品接口和具体产品类。适用于创建对象种类较少且调用者无需关心创建细节的场景。优点是封装性强、代码复用性好;缺点是扩展性差,增加新产品时需修改工厂类代码,违反开闭原则。
44 15
|
3月前
|
设计模式 开发者 Python
Python编程中的设计模式:工厂方法模式###
本文深入浅出地探讨了Python编程中的一种重要设计模式——工厂方法模式。通过具体案例和代码示例,我们将了解工厂方法模式的定义、应用场景、实现步骤以及其优势与潜在缺点。无论你是Python新手还是有经验的开发者,都能从本文中获得关于如何在实际项目中有效应用工厂方法模式的启发。 ###
|
3月前
|
设计模式 安全 Java
Kotlin - 改良设计模式 - 构建者模式
Kotlin - 改良设计模式 - 构建者模式
|
3月前
|
设计模式 安全 Java
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
63 1
|
4月前
|
设计模式 Java Kotlin
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
本教程详细讲解Kotlin语法,适合希望深入了解Kotlin的开发者。对于快速学习Kotlin语法,推荐查看“简洁”系列教程。本文重点介绍了构建者模式在Kotlin中的应用与改良,包括如何使用具名可选参数简化复杂对象的创建过程,以及如何在初始化代码块中对参数进行约束和校验。
46 3

热门文章

最新文章