【声明】本题目来源于卡码网(题目页面 (kamacoder.com))
【提示:如果不想看文字介绍,可以直接跳转到C++编码部分】
【简介】什么是桥接模式
桥接模式(Bridge Pattern)是⼀种结构型设计模式,它的UML图很像⼀座桥,它通过将【抽象部分】与【实现部分】分离,使它们可以独⽴变化,从⽽达到降低系统耦合度的⽬的。桥接模式的主要⽬的是通过组合建⽴两个类之间的联系,⽽不是继承的⽅式。
举个简单的例⼦,图形编辑器中,每⼀种图形都需要蓝⾊、红⾊、⻩⾊不同的颜⾊,如果不使⽤桥接模式,可能需要为每⼀种图形类型和每⼀种颜⾊都创建⼀个具体的⼦类,⽽使⽤桥接模式可以将图形和颜⾊两个维度分离,两个维度都可以独⽴进⾏变化和扩展,如果要新增其他颜⾊,只需添加新的 Color ⼦类,不影响图形类;反之亦然。
【基本结构】
桥接模式的基本结构分为以下⼏个⻆⾊:
- 抽象Abstraction :⼀般是抽象类,定义抽象部分的接⼝,维护⼀个对【实现】的引⽤。
- 修正抽象RefinedAbstaction :对抽象接⼝进⾏扩展,通常对抽象化的不同维度进⾏变化或定制。
- 实现Implementor : 定义实现部分的接⼝,提供具体的实现。这个接⼝通常是抽象化接⼝的实现。
- 具体实现ConcreteImplementor :实现实现化接⼝的具体类。这些类负责实现实现化接⼝定义的具体操作。
再举个例⼦,遥控器就是抽象接⼝,它具有开关电视的功能,修正抽象就是遥控器的实例,对遥控器的功能进⾏实现和扩展,⽽电视就是实现接⼝,具体品牌的电视机是具体实现,遥控器中包含⼀个对电视接⼝的引⽤,通过这种⽅式,遥控器和电视的实现被分离,我们可以创建多个遥控器,每个遥控器控制⼀个品牌的电视机,它们之间独⽴操作,不受电视品牌的影响,可以独⽴变化。
【简易实现】
下⾯是实现桥接模式的基本步骤:(以Java代码作以说明)
1. 创建实现接口
interface Implementation {
void operationImpl();
}
2. 创建具体实现类:实际提供服务的对象
class ConcreteImplementationA implements Implementation {
@Override
public void operationImpl() {
// 具体实现A
}
}
class ConcreteImplementationB implements Implementation {
@Override
public void operationImpl() {
// 具体实现B
}
}
3. 创建抽象接⼝:包含⼀个对实现化接⼝的引⽤。
public abstract class Abstraction {
protected IImplementor mImplementor;
public Abstraction(IImplementor implementor) {
this.mImplementor = implementor;
}
public void operation() {
this.mImplementor.operationImpl();
}
}
4. 实现抽象接⼝,创建RefinedAbstaction 类
class RefinedAbstraction implements Abstraction {
private Implementation implementation;
public RefinedAbstraction(Implementation implementation) {
this.implementation = implementation;
}
@Override
public void operation() {
// 委托给实现部分的具体类
implementation.operationImpl();
}
}
5. 客户端使⽤
// 客户端代码
public class Main {
public static void main(String[] args) {
// 创建具体实现化对象
Implementation implementationA = new ConcreteImplementationA();
Implementation implementationB = new ConcreteImplementationB();
// 使⽤扩充抽象化对象,将实现化对象传递进去
Abstraction abstractionA = new RefinedAbstraction(implementationA);
Abstraction abstractionB = new RefinedAbstraction(implementationB);
// 调⽤抽象化的操作
abstractionA.operation();
abstractionB.operation();
}
}
【使用场景】
桥接模式在⽇常开发中使⽤的并不是特别多,通常在以下情况下使⽤:
- 当⼀个类存在两个独⽴变化的维度,⽽且这两个维度都需要进⾏扩展时,使⽤桥接模式可以使它们独⽴变化,减少耦合。
- 不希望使⽤继承,或继承导致类爆炸性增⻓
总体⽽⾔,桥接模式适⽤于那些有多个独⽴变化维度、需要灵活扩展的系统。
【编码部分】
1. 题目描述
小明家有一个万能遥控器,能够支持多个品牌的电视。每个电视可以执行开机、关机和切换频道的操作,请你使用桥接模式模拟这个操作。
2. 输入描述
第一行是一个整数 N(1 <= N <= 100),表示后面有 N 行输入。接下来的 N 行,每行包含两个数字。第一个数字表示创建某个品牌的遥控和电视,第二个数字表示执行的操作。其中,0 表示创建 Sony 品牌的电视,1 表示创建 TCL 品牌的遥控和电视;2 表示开启电视、3表示关闭电视,4表示切换频道。
3. 输出描述
对于每个操作,输出相应的执行结果。
4. C++编码实例
/**
* @version Copyright (c) 2024 NCDC, Servo。 Unpublished - All rights reserved
* @file BridgeMode.hpp
* @brief 桥接模式
* @autor 写代码的小恐龙er
* @date 2024/01/11
*/
#include <iostream>
#include <string>
using namespace std;
// 前置声明
// 实现化接口
class TV;
// ======== 第一个维度的扩充 ========
// 具体实现类1 -- Sony Tv
class SonyTv;
// 具体实现类2 -- TCL Tv
class TclTv;
// ----------------------------------
// 抽象化接口
class RemoteControl;
// ======== 第二个维度的扩充 ========
// 实现抽象化接口 -- 开机
class TurnOn;
// 实现抽象化接口 -- 关机
class TurnOff;
// 实现抽象化接口 -- 切换频道
class SwitchChannel;
// 实现化接口
class TV
{
// 接口函数
public:
virtual void TurnOnTV() = 0;
virtual void TurnOffTV() = 0;
virtual void SwitchTVChannel() = 0;
};
// 具体实现类1 -- Sony Tv
class SonyTv : public TV
{
public:
// 重载接口函数
void TurnOnTV(){
std::cout << "Sony TV is ON" << endl;
}
void TurnOffTV(){
std::cout << "Sony TV is OFF" << endl;
}
void SwitchTVChannel(){
std::cout << "Switching Sony TV channel" << endl;
}
};
// 具体实现类2 -- TCL Tv
class TclTv : public TV
{
public:
// 重载接口函数
void TurnOnTV(){
std::cout << "TCL TV is ON" << endl;
}
void TurnOffTV(){
std::cout << "TCL TV is OFF" << endl;
}
void SwitchTVChannel(){
std::cout << "Switching TCL TV channel" << endl;
}
};
// 抽象化接口
class RemoteControl
{
// 抽象化接口类持有实现化接口类的实例
protected:
TV *_tv;
public:
// 重载构造函数
RemoteControl(){}
RemoteControl(TV *tv){
this->_tv = tv;
}
// 提供抽象类接口函数
virtual void OperationMode() = 0;
};
// 实现抽象化接口 -- 开机
class TurnOn : public RemoteControl
{
private:
// 实现抽象接口类持有实现化接口类的实例
TV *_tv;
public:
// 重载构造函数 以便后续调用能传入抽象类
TurnOn(TV *tv){
this->_tv = tv;
}
// 重载抽象类接口函数
void OperationMode() override {
this->_tv->TurnOnTV();
}
};
// 实现抽象化接口 -- 关机
class TurnOff : public RemoteControl
{
private:
// 实现抽象接口类持有实现化接口类的实例
TV *_tv;
public:
// 重载构造函数 以便后续调用能传入抽象类
TurnOff(TV *tv){
this->_tv = tv;
}
// 重载抽象类接口函数
void OperationMode() override {
this->_tv->TurnOffTV();
}
};
// 实现抽象化接口 -- 切换频道
class SwitchChannel : public RemoteControl
{
private:
// 实现抽象接口类持有实现化接口类的实例
TV *_tv;
public:
// 重载构造函数 以便后续调用能传入抽象类
SwitchChannel(TV *tv){
this->_tv = tv;
}
// 重载抽象类接口函数
void OperationMode() override {
this->_tv->SwitchTVChannel();
}
};
int main()
{
// 执行操作的数量
int operationNum = 0;
// 输入
std::cin >> operationNum;
// 创建实现化接口
TV *tv = nullptr;
RemoteControl *control = nullptr;
// 遍历输入
for(int i = 0; i < operationNum; i++)
{
// 电视机类型
int tvType = -1;
// 遥控器操作类型
int controlType = -1;
// 输入
std:: cin >> tvType >> controlType;
// 电视机类型
if(!tvType){
tv = new SonyTv();
}
else if(tvType == 1){
tv = new TclTv();
}
else tv = nullptr;
// 若输入指令错误则直接返回
if(tv == nullptr) return 0;
// 遥控器操作类型
if(controlType == 2){
control = new TurnOn(tv);
}
else if(controlType == 3){
control = new TurnOff(tv);
}
else if(controlType == 4){
control = new SwitchChannel(tv);
}
else control = nullptr;
// 若输入指令错误则直接返回
if(control == nullptr) return 0;
// 执行操作
control->OperationMode();
}
delete tv;
tv = nullptr;
delete control;
control = nullptr;
return 0;
}
......
To be continued.