当前位置: 首页 > article >正文

【再谈设计模式】桥接模式 ~ 抽象与实现的灵活桥梁

一、引言

        在软件开发过程中,软件设计中,面对复杂性和变化性时,设计模式提供了一种优雅的解决方案。桥接模式(Bridge Pattern)是一种结构型设计模式,它通过将抽象与实现分离来实现灵活的扩展。本文将深入探讨桥接模式的定义、适用场景、现实生活中的例子,以及在不同编程语言中的实现示例,最后分析其优缺点并讨论其升级版。

二、定义与描述

        桥接模式的核心思想是将一个类的抽象部分与其实现部分分离,使它们可以独立变化。通过这种方式,桥接模式能够降低系统的复杂性,提高代码的可扩展性和可维护性。

结构

桥接模式主要包含以下几个角色:

  • 抽象类(Abstraction):定义了高层接口,包含一个对实现部分的引用。
  • 扩展抽象类(Refined Abstraction):扩展了抽象类的接口。
  • 实现类接口(Implementor):定义了实现类的接口,但不一定要与抽象类的接口完全一致。
  • 具体实现类(Concrete Implementor):实现了实现类接口的具体类。

三、抽象背景

        在软件开发中,常常会遇到需要同时改变多个维度的情况。例如,在图形绘制应用中,我们可能需要同时支持不同的形状(如圆形、方形)和不同的颜色(如红色、蓝色)。如果直接使用继承的方式来处理,可能会导致类的数量急剧增加,进而导致系统复杂性增加。

四、适用场景与现实问题解决

适用于场景

  • 系统需要在多个维度上进行扩展:如图形、颜色、形状等。
  • 避免在抽象和实现之间的紧耦合:当实现变化频繁时,桥接模式可以减少修改的影响。
  • 需要在运行时选择实现:如不同平台上的功能实现。

现实问题解决

        假设我们在开发一个图形绘制应用,需要支持多种形状和颜色。使用桥接模式,我们可以将形状和颜色的实现分开,使得添加新形状或新颜色时不需要修改已有的代码。

五、现实生活中的例子

遥控器和设备

        想象一下,遥控器是一个抽象类,而具体的设备(如电视、空调、音响等)是实现类。遥控器可以有不同的品牌和型号,但它可以控制多种设备。通过桥接设计模式,遥控器的操作(如开关、调节音量)与具体设备的实现分开,这样你可以轻松添加新设备或新遥控器而不需要修改已有的代码。

  • 抽象类:遥控器(RemoteControl)
  • 实现类:电视(TV)、空调(AirConditioner)
  • 桥接:遥控器可以通过不同的设备接口实现不同的控制方式。

 图形绘制

        在图形绘制软件中,可以有不同的形状(如圆形、方形)和不同的绘图方式(如矢量绘图、位图绘图)。在这个例子中,形状是抽象类,而具体的绘图方式是实现类。通过桥接设计模式,用户可以在不改变形状的情况下,选择不同的绘图方式,或者在不改变绘图方式的情况下,添加新的形状。

  • 抽象类:形状(Shape)
  • 实现类:矢量绘图(VectorDrawing)、位图绘图(RasterDrawing)
  • 桥接:不同的形状可以使用不同的绘图方式进行绘制,灵活性更高。

六、各种编程语言的实现示例

代码设计

类图:

  • Device是一个接口,定义了turnOnturnOff方法,TVRadio类实现了该接口,表示具体的设备。
  • RemoteControl是抽象类,包含了对Device的引用,并且有抽象的turnOnturnOff方法。
  • AdvancedRemoteControlRemoteControl的具体扩展类,实现了抽象类中的turnOnturnOff方法,通过调用所关联的Device的相应方法来实现功能。
  • 关联关系表示了RemoteControl及其子类与Device之间的依赖关系,即通过持有Device对象来实现对不同设备的控制操作。

流程图:

  • 首先开始流程,然后依次展示了创建电视设备、创建关联电视的高级遥控器并进行打开和关闭电视的操作步骤。
  • 接着又展示了创建收音机设备、创建关联收音机的高级遥控器并进行打开和关闭收音机的操作步骤。
  • 最后流程结束。

Java实现

// 实现类接口
interface Device {
    void turnOn();
    void turnOff();
}

// 具体实现类
class TV implements Device {
    public void turnOn() {
        System.out.println("电视打开");
    }
    
    public void turnOff() {
        System.out.println("电视关闭");
    }
}

class Radio implements Device {
    public void turnOn() {
        System.out.println("收音机打开");
    }
    
    public void turnOff() {
        System.out.println("收音机关闭");
    }
}

// 抽象类
abstract class RemoteControl {
    protected Device device;

    public RemoteControl(Device device) {
        this.device = device;
    }

    abstract void turnOn();
    abstract void turnOff();
}

// 扩展抽象类
class AdvancedRemoteControl extends RemoteControl {
    public AdvancedRemoteControl(Device device) {
        super(device);
    }

    public void turnOn() {
        device.turnOn();
    }

    public void turnOff() {
        device.turnOff();
    }
}

// 客户端代码
public class BridgePatternDemo {
    public static void main(String[] args) {
        Device tv = new TV();
        RemoteControl remote = new AdvancedRemoteControl(tv);
        remote.turnOn();
        remote.turnOff();
        
        Device radio = new Radio();
        remote = new AdvancedRemoteControl(radio);
        remote.turnOn();
        remote.turnOff();
    }
}

C++实现

#include <iostream>
using namespace std;

// 实现类接口
class Device {
public:
    virtual void turnOn() = 0;
    virtual void turnOff() = 0;
};

// 具体实现类
class TV : public Device {
public:
    void turnOn() override {
        cout << "电视打开" << endl;
    }
    
    void turnOff() override {
        cout << "电视关闭" << endl;
    }
};

class Radio : public Device {
public:
    void turnOn() override {
        cout << "收音机打开" << endl;
    }
    
    void turnOff() override {
        cout << "收音机关闭" << endl;
    }
};

// 抽象类
class RemoteControl {
protected:
    Device* device;

public:
    RemoteControl(Device* device) : device(device) {}
    virtual void turnOn() = 0;
    virtual void turnOff() = 0;
};

// 扩展抽象类
class AdvancedRemoteControl : public RemoteControl {
public:
    AdvancedRemoteControl(Device* device) : RemoteControl(device) {}

    void turnOn() override {
        device->turnOn();
    }

    void turnOff() override {
        device->turnOff();
    }
};

// 客户端代码
int main() {
    Device* tv = new TV();
    RemoteControl* remote = new AdvancedRemoteControl(tv);
    remote->turnOn();
    remote->turnOff();
    
    Device* radio = new Radio();
    remote = new AdvancedRemoteControl(radio);
    remote->turnOn();
    remote->turnOff();

    delete tv;
    delete radio;
    delete remote;
    return 0;
}

Python实现

# 实现类接口
class Device:
    def turn_on(self):
        pass

    def turn_off(self):
        pass

# 具体实现类
class TV(Device):
    def turn_on(self):
        print("电视打开")

    def turn_off(self):
        print("电视关闭")

class Radio(Device):
    def turn_on(self):
        print("收音机打开")

    def turn_off(self):
        print("收音机关闭")

# 抽象类
class RemoteControl:
    def __init__(self, device):
        self.device = device

    def turn_on(self):
        pass

    def turn_off(self):
        pass

# 扩展抽象类
class AdvancedRemoteControl(RemoteControl):
    def turn_on(self):
        self.device.turn_on()

    def turn_off(self):
        self.device.turn_off()

# 客户端代码
if __name__ == "__main__":
    tv = TV()
    remote = AdvancedRemoteControl(tv)
    remote.turn_on()
    remote.turn_off()

    radio = Radio()
    remote = AdvancedRemoteControl(radio)
    remote.turn_on()
    remote.turn_off()

Go实现

package main

import "fmt"

// 实现类接口
type Device interface {
	turnOn()
	turnOff()
}

// 具体实现类
type TV struct{}

func (t *TV) turnOn() {
	fmt.Println("电视打开")
}

func (t *TV) turnOff() {
	fmt.Println("电视关闭")
}

type Radio struct{}

func (r *Radio) turnOn() {
	fmt.Println("收音机打开")
}

func (r *Radio) turnOff() {
	fmt.Println("收音机关闭")
}

// 抽象类
type RemoteControl struct {
	device Device
}

func (r *RemoteControl) turnOn() {
	r.device.turnOn()
}

func (r *RemoteControl) turnOff() {
	r.device.turnOff()
}

// 客户端代码
func main() {
	tv := &TV{}
	remote := &RemoteControl{device: tv}
	remote.turnOn()
	remote.turnOff()

	radio := &Radio{}
	remote.device = radio
	remote.turnOn()
	remote.turnOff()
}

七、桥接模式的优缺点

优点

  • 分离抽象与实现:使得抽象和实现可以独立变化,降低了耦合度。
  • 提高可扩展性:可以方便地添加新的实现或抽象,而不需要修改现有代码。
  • 简化代码结构:避免了类的膨胀,使得代码更加清晰。

缺点

  • 增加了系统复杂性:引入了额外的抽象层,可能使得系统更加复杂。
  • 需要更多的类:为了实现桥接模式,可能需要创建更多的类,增加了管理的复杂性。

八、桥接模式的升级版

        桥接模式的升级版可以结合其他设计模式使用,如适配器模式、组合模式(Composite Pattern)和策略模式(Strategy Pattern)。通过组合这些模式,可以实现更复杂的功能。例如,在图形绘制中,可以使用桥接模式将形状与颜色分离,同时使用组合模式管理不同形状的组合。


http://www.kler.cn/a/421810.html

相关文章:

  • FilterListenerAjax
  • 洛谷 B2029:大象喝水 ← 圆柱体体积
  • 【AI日记】24.12.03 kaggle 比赛 Titanic-6
  • 【阅读记录-章节5】Build a Large Language Model (From Scratch)
  • Zookeeper集群数据是如何同步的?
  • linux 压缩命令,压缩a目录,但是不压缩a目录下的b目录,zip命令
  • Selenium3+Python如何操作键盘
  • Python的秘密基地--[章节2]Python核心数据结构
  • JDBC入门
  • 深度学习入门课程学习笔记(第23周)
  • SpringBoot 框架下基于 MVC 的高校办公室行政事务管理系统:设计开发全解析
  • 【机器学习】支持向量机SVR、SVC分析简明教程
  • C哈的刷题计划之二维表格数据填充(2)
  • SpringCloud框架学习(第七部分:分布式事务Seata)
  • 产品转后端?2
  • Linux环境下完全卸载、安装Docker以及常用命令
  • Pytest框架学习21--fixture总结
  • 2-2-18-9 QNX系统架构之文件系统(一)
  • 二分搜索(三)x的平方根
  • Midjourney Imagine API 申请及使用
  • Vue2-从零搭建一个项目(项目基本结构介绍)
  • 智能运维视角下的网络设备监测与数据分析
  • Flutter中的Future和Stream
  • Pytorch实现心跳信号分类识别(支持LSTM,GRU,TCN模型)
  • 【论文精读】Revisiting Adversarial Training under Long-Tailed Distributions
  • 组合问题变式——选数(dfs)