桥接模式:将抽象部分与它的实现部分分离,使它们可以独立地变化。
设想如果要绘制矩形、圆形、椭圆、正方形,我们至少需要4个形状类,但是如果绘制的图形需要具有不同的颜色,
如红色、绿色、蓝色等,此时至少有如下两种设计方案:
- 第一种设计方案是为每一种形状都提供一套各种颜色的版本;
- 第二种设计方案是根据实际需要对形状和颜色进行组合。
对于有两个变化维度(即两个变化的原因)的系统,采用方案二来进行设计系统中类的个数更少,且系统扩展更为方便。
设计方案二即是桥接模式的应用。桥接模式将继承关系转换为关联关系,从而降低了类与类之间的耦合,减少了代码编写量。
桥接模式包含如下角色:
- shape:图形抽象类
- retangle,circle:图形扩充抽象类
- color:颜色实现类接口
- red,yellow:具体颜色实现类
- 4.1 c++代码实现
- 4.1.1 main.cpp
/**
* @file main.cpp
* @brief
* @version 0.1
* @date 2022-04-02
*
* @copyright Copyright (c) 2022
*
*/
#include
#include"shape.hpp"
#include"color.hpp"
using namespace std;
void test_inline_bridge() {
color* clr = new yellow();
shape* shp = new circle(clr);
shp->draw();
cout << "-----------------------" << endl;
clr = new red();
shp = new circle(clr);
shp->draw();
cout << "-----------------------" << endl;
clr = new red();
shp = new retangle(clr);
shp->draw();
cout << "-----------------------" << endl;
clr = new yellow();
shp = new retangle(clr);
shp->draw();
cout << "-----------------------" << endl;
}
int main(int argc, const char** argv) {
test_inline_bridge();
return 0;
}
- 4.1.2 color.hpp
//===========================================================
/**
* @file color.hpp
* @brief
* @version 0.1
* @date 2022-04-02
*
* @copyright Copyright (c) 2022
*
*/
#ifndef D50611F4_86D1_48F4_BCA6_3AFD4AE61BAC
#define D50611F4_86D1_48F4_BCA6_3AFD4AE61BAC
#include<iostream>
using namespace std;
// 颜色抽象接口
class color
{
public:
color(){};
virtual ~color(){};
virtual void choose_color(){};
};
class red: public color {
public:
red(){};
~red(){};
void choose_color(){
cout << "choose_color red" << endl;
};
};
class yellow: public color {
public:
yellow(){};
~yellow(){};
void choose_color(){
cout << "choose_color yellow" << endl;
};
};
class blue: public color {
public:
blue(){};
~blue(){};
void choose_color(){
cout << "choose_color blue" << endl;
};
};
#endif /* D50611F4_86D1_48F4_BCA6_3AFD4AE61BAC */
- 4.1.3 shape.hpp
//===========================================================
/**
* @file shape.hpp
* @brief
* @version 0.1
* @date 2022-04-02
*
* @copyright Copyright (c) 2022
*
*/
#ifndef F45EC17B_C10E_4F7B_A409_1D60017EF5CE
#define F45EC17B_C10E_4F7B_A409_1D60017EF5CE
#include <iostream>
#include"color.hpp"
using namespace std;
// 图形抽象接口
class shape {
private:
color* m_clr;
protected:
color* get_clr() {
return m_clr;
}
public:
shape(color* clr): m_clr(clr) {};
virtual ~shape(){
delete m_clr;
};
virtual void draw(){};
};
class circle: public shape
{
public:
circle(color* clr): shape(clr){};
~circle(){};
void draw(){
cout << "circle::draw" << endl;
get_clr()->choose_color();
}
};
class retangle: public shape
{
public:
retangle(color* clr):shape(clr){};
~retangle(){};
void draw(){
cout << "retangle::draw" << endl;
get_clr()->choose_color();
}
};
class triangle: public shape
{
public:
triangle(color* clr):shape(clr){};
~triangle(){};
void draw(){
cout << "triangle::draw" << endl;
get_clr()->choose_color();
}
};
#endif /* F45EC17B_C10E_4F7B_A409_1D60017EF5CE */
-
4.2 go代码实现: go实现和c++实现有点不一样, 因为go的接口类不能带有成员变量,故通过参数将其传入,这个安全性没有c++好。
-
4.3 color.go和shape.go在main.go同一级目录的bridge的包下,代码如下:
-
4.3.1:color.go
// color.go
package bridge
import (
"fmt"
)
// ==================================================
// 颜色抽象接口
type IColor interface{
ChooseColor()
}
// ==================================================
type Red struct {
}
func NewRed() *Red {
return &Red{}
}
func (r *Red) ChooseColor() {
fmt.Println("ChooseColor::Red")
}
// ==================================================
type Yellow struct {
}
func NewYellow() *Yellow {
return &Yellow{}
}
func (y *Yellow) ChooseColor() {
fmt.Println("ChooseColor::Yellow")
}
// ==================================================
type Blue struct {
}
func NewBlue() *Blue {
return &Blue{}
}
func (b *Blue) ChooseColor() {
fmt.Println("ChooseColor::Blue")
}
- 4.3.2:shape.go
package bridge
import (
"fmt"
)
// ==================================================
// 图形抽象接口
type IShape interface{
Draw(clr IColor)
}
// ==================================================
type Circle struct {
}
func NewCircle() *Circle {
return &Circle{}
}
func (c *Circle) Draw(clr IColor) {
fmt.Println("Circle::Draw")
clr.ChooseColor()
fmt.Println("---------------------------")
}
// ==================================================
type Retangle struct {}
func NewRetangle() *Retangle {
return &Retangle{}
}
func (r *Retangle) Draw(clr IColor) {
fmt.Println("Retangle::Draw")
clr.ChooseColor()
fmt.Println("---------------------------")
}
- 4.3.3:main.go
package main
import (
"./bridge"
)
func main() {
var ishp bridge.IShape = bridge.NewCircle()
ishp.Draw(bridge.NewRed())
ishp.Draw(bridge.NewYellow())
ishp.Draw(bridge.NewBlue())
var itshp bridge.IShape = bridge.NewRetangle()
itshp.Draw(bridge.NewRed())
itshp.Draw(bridge.NewYellow())
itshp.Draw(bridge.NewBlue())
}
- 4.3.3:执行结果:
Circle::Draw
ChooseColor::Red
---------------------------
Circle::Draw
ChooseColor::Yellow
---------------------------
Circle::Draw
ChooseColor::Blue
---------------------------
Retangle::Draw
ChooseColor::Red
---------------------------
Retangle::Draw
ChooseColor::Yellow
---------------------------
Retangle::Draw
ChooseColor::Blue
---------------------------
5.模式分析
理解桥接模式,重点需要理解如何将抽象化(Abstraction)与实现化(Implementation)脱耦,使得二者可以独立地变化。
- 抽象化:抽象化就是忽略一些信息,把不同的实体当作同样的实体对待。
在面向对象中,将对象的共同性质抽取出来形成类的过程即为抽象化的过程。 - 实现化:针对抽象化给出的具体实现,就是实现化,抽象化与实现化是一对互逆的概念,
实现化产生的对象比抽象化更具体,是对抽象化事物的进一步具体化的产物。 - 脱耦:脱耦就是将抽象化和实现化之间的耦合解脱开,或者说是将它们之间的强关联改换成弱关联,
将两个角色之间的继承关系改为关联关系。桥接模式中的所谓脱耦,就是指在一个软件系统的抽象化和实现化之间使用关联关系(组合或者聚合关系)而不是继承关系,
从而使两者可以相对独立地变化,这就是桥接模式的用意。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)