千家信息网

设计模式(结构型)之桥梁模式

发表于:2025-02-03 作者:千家信息网编辑
千家信息网最后更新 2025年02月03日,GOF 在《设计模式》中给桥梁模式的定义为:将抽象部分与它的实现部分分离,使它们都可以独立地变化。这里的抽象部分和实现部分不是我们通常认为的父类与子类、接口与实现类的关系,而是组合关系。也就是说,实现
千家信息网最后更新 2025年02月03日设计模式(结构型)之桥梁模式

GOF 在《设计模式》中给桥梁模式的定义为:将抽象部分与它的实现部分分离,使它们都可以独立地变化。这里的抽象部分和实现部分不是我们通常认为的父类与子类、接口与实现类的关系,而是组合关系。也就是说,实现部分是被抽象部分调用,以用来完成(实现)抽象部分的功能。

桥梁模式的用意是"将抽象化(Abstraction)和实现化(Implementation)脱耦,使得二者可以独立地变化。"

抽象化:

存在于多个实体中的共同的概念性联系,就是抽象化。

实现化:

抽象化给出的具体实现,就是实现化。

脱耦:

耦合,就是两个实体的行为的某种强关联。脱耦,就是将这种强关联去掉。

强关联,就是在编译时期就确定了,无法在运行时期动态改变的关联。

弱关联,就是可以动态地确定,并可以在运行时期动态地改变的关联。

Java中,继承关系是强关联组合(聚合)关系是软关联

一、组成:

1) 抽 象 ( Abstraction ) 角色: 它定义了抽象类的接口而且维护着一个指向实现角色的引用
2) 精确\修正抽象(RefinedAbstraction\SpecializedAbstraction)角色:实现并扩充由抽象角色定义的接口。
3) 实现(Implementor)角色:给出了实现类的接口,这里的接口与抽象角色中的接口可以不一致实现化角色应当只给出底层操作,而抽象化角色应当只给出基于底层操作的更高一层的操作
4) 具体实现(ConcreteImplementor)角色:给出了实现角色定义接口的具体实现。

二、UML类图:

三、类图的代码描述(JAVA):

以下代码来自《Thinking in Patterns with Java》:

//抽象部分的抽象角色
class Abstraction {
//维护着一个指向实现(Implementor)角色的引用
private Implementation implementation;
public Abstraction(Implementation imp) {
implementation = imp;
}
// 下面定义了抽象部分应该有的接口
public void service1() {
//使用了实现部分已有的接口
//组合实现功能
implementation.facility1();
implementation.facility2();
}
public void service2() {
implementation.facility2();
implementation.facility3();
}
public void service3() {
implementation.facility1();
implementation.facility2();
implementation.facility4();
}
// For use by subclasses:
protected Implementation getImplementation() {
return implementation;
}
}


//抽象部分的精确抽象角色
class ClientService1 extends Abstraction {
public ClientService1(Implementation imp) {

super(imp);

}
//使用抽象角色提供的方法组合起来完成某项功能
//这就是为什么叫精确抽象角色(修正抽象角色)
public void serviceA() {
service1();
service2();
}
public void serviceB() {
service3();
}
}
//另一个精确抽象角色,和上面一样的被我省略了
class ClientService2 extends Abstraction {
//这里是直接通过实现部分的方法来实现一定的功能
public void serviceE() {
getImplementation().facility3();
}
}


//实现部分的实现角色
interface Implementation {
//这个接口只是定义了一定的接口
void facility1();
void facility2();
void facility3();
void facility4();
}


//具体实现角色就是要将实现角色提供的接口实现
//并完成一定的功能
//这里省略了
class Implementation1 implements Implementation {

......

}

class Implementation2 implements Implementation {

......

}

......

在上面的程序中还体现出一点特色:就是不仅实现部分和抽象部分所提供的接口可以完全不一样;而且实现部分内部、抽象部分内部的接口也完全可以不一样。但是实现部分要提供类似的功能才行。

四、详细代码实现:

在这里,我用了一个具体的例子:

现在我要画画,要画矩形(Rectangle)和三角形(Triangle)两种形状的形状(Shape),但是我又要画实线(SolidLine)和虚线(DotLine)两种线条(Line)

这样,我们就可以把形状看成抽象化,把线条看成实现化矩形和三角形就是修正抽象化,实线和虚线就是具体实现化

JAVA:

Shape.java:

// 抽象化角色

package abstraction;
import implementation.Line;
public class Shape {
protected Line line;


protected int x1;
protected int y1;
protected int x2;
protected int y2;

public Shape(){}
public Shape(Line line,int x1, int y1, int x2, int y2){
this.line = line;
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}
public void show(){

}
public int calculateArea(){
return 0;
}
public int calculatePerimeter(){
return 0;
}
}

Rectangle.java:

// 修正抽象化角色

package abstraction;

import implementation.Line;

public class Rectangle extends Shape {
public Rectangle(Line line,int x1, int y1, int x2, int y2){
super(line, x1, y1, x2, y2);
}

public void show(){
System.out.println("This is an Rectangle!");
line.draw(x1, y1, x2, y2);
}
public int calculateArea(){
return Math.abs((x2 - x1)*(y2 - y1));
}
public int calculatePerimeter(){
return 2*(Math.abs(x2 - x1) + Math.abs(y2 - y1));
}

}


Triangle.java:

// 修正抽象化角色

package abstraction;

import implementation.Line;

public class Triangle extends Shape {
public Triangle(Line line,int x1, int y1, int x2, int y2){
super(line, x1, y1, x2, y2);
}

public void show(){
System.out.println("This is an Triangle!");
line.draw(x1, y1, x2, y2);
}
public int calculateArea(){
return Math.abs((x2 - x1)*(y2 - y1))/2;
}
public int calculatePerimeter(){
int a = Math.abs(x2 - x1);
int b = Math.abs(y2 - y1);
int c = (int)Math.sqrt(a*a + b*b);
return a + b + c;
}

}

Line.java:

// 实现化角色

package implementation;

public class Line {
protected int x1;
protected int y1;
protected int x2;
protected int y2;
public void draw(int x1, int y1, int x2, int y2){

}
}

DotLine.java:

// 具体实现化角色

package implementation;

public class DotLine extends Line {
protected int x1;
protected int y1;
protected int x2;
protected int y2;
public void draw(int x1, int y1, int x2, int y2){
System.out.println("drawSolidLine:"+x1+","+y1+","+x2+","+y2);
}
}

SolidLine.java:

// 具体实现化角色

package implementation;

public class SolidLine extends Line {
protected int x1;
protected int y1;
protected int x2;
protected int y2;
public void draw(int x1, int y1, int x2, int y2){
System.out.println("drawDotLine:"+x1+","+y1+","+x2+","+y2);
}
}

mainDraw.java:

// 实现

import abstraction.*;
import implementation.*;

public class mainDraw {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int x1=0, y1=0, x2=1, y2=1;
Line solidLine = new SolidLine();
Line dotLine = new DotLine();
Shape solidLineRectangle = new Rectangle(solidLine,x1, y1, x2, y2);
Shape dotLineRectangle = new Rectangle(dotLine,x1, y1, x2, y2);
Shape solidLineTriangle = new Triangle(solidLine,x1, y1, x2, y2);
Shape dotLineTriangle = new Triangle(dotLine,x1, y1, x2, y2);

System.out.println("########################");
System.out.println("solidLineRectangle:");
solidLineRectangle.show();
System.out.println("area:"+solidLineRectangle.calculateArea());
System.out.println("perimeter:"+solidLineRectangle.calculatePerimeter());
System.out.println("########################");
System.out.println("dotLineRectangle:");
dotLineRectangle.show();
System.out.println("area:"+dotLineRectangle.calculateArea());
System.out.println("perimeter:"+dotLineRectangle.calculatePerimeter());
System.out.println("########################");
System.out.println("solidLineTriangle:");
solidLineTriangle.show();
System.out.println("area:"+solidLineTriangle.calculateArea());
System.out.println("perimeter:"+solidLineTriangle.calculatePerimeter());
System.out.println("########################");
System.out.println("dotLineTriangle:");
dotLineTriangle.show();
System.out.println("area:"+dotLineTriangle.calculateArea());
System.out.println("perimeter:"+dotLineTriangle.calculatePerimeter());

}

}

输出结果:

########################
solidLineRectangle:
This is an Rectangle!
drawDotLine:0,0,1,1
area:1
perimeter:4
########################
dotLineRectangle:
This is an Rectangle!
drawSolidLine:0,0,1,1
area:1
perimeter:4
########################
solidLineTriangle:
This is an Triangle!
drawDotLine:0,0,1,1
area:0
perimeter:3
########################
dotLineTriangle:
This is an Triangle!
drawSolidLine:0,0,1,1
area:0
perimeter:3

C++:

shape.h(定义在include包中):

// 抽象化角色

#ifndef SHAPE_H_
#define SHAPE_H_
#include "lines.h"
#include
using namespace std;

class Shape{
public:
Shape(){}
Shape(Line &line,int x1, int y1, int x2, int y2){
this->line = &line;
this->x1 = x1;
this->y1 = y1;
this->x2 = x2;
this->y2 = y2;
}
virtual void show() = 0;
virtual int calculateArea() = 0;
virtual int calculatePerimeter() = 0;
virtual ~Shape(){}
protected:
Line* line;
int x1, y1, x2, y2;
};

class Rectangle : public Shape{
public:
Rectangle(Line &line,int x1, int y1, int x2, int y2);
int calculateArea();
int calculatePerimeter();
void show();
virtual ~Rectangle(){}
protected:
int x1, y1, x2, y2;
};


class Triangle : public Shape {
public:
Triangle(Line &line,int x1, int y1, int x2, int y2);
void show();
int calculateArea();
int calculatePerimeter();
private:
int x1, y1, x2, y2;
};

#endif

line.h(定义在include包中):

// 实现化角色

#ifndef LINES_H_
#define LINES_H_

class Line{
public:
virtual void draw(int x1, int y1, int x2, int y2) = 0;
virtual ~Line(){};
};

class SolidLine:public Line{
public:
void draw(int x1, int y1, int x2, int y2);
virtual ~SolidLine(){};
};

class DotLine:public Line{
public:
void draw(int x1, int y1, int x2, int y2);
virtual ~DotLine(){};
};

#endif /* LINES_H_ */

Rectangle.cpp:

// 修正实现角色

#include "../include/shape.h"
#include

Rectangle::Rectangle(Line &line,int x1, int y1, int x2, int y2){
this->line = &line;
this->x1 = x1;
this->y1 = y1;
this->x2 = x2;
this->y2 = y2;
}

int Rectangle::calculateArea(){
return abs((x2 - x1)*(y2 - y1));
}

int Rectangle::calculatePerimeter(){
return 2*(abs(x2 - x1) + abs(y2 - y1));
}


void Rectangle::show(){
cout << "Rectangle" << endl;
line->draw(x1, y1, x1, y2);
}

Triangle.cpp:

// 修正实现角色

#include "../include/shape.h"
#include
#include

Triangle::Triangle(Line &line, int x1, int y1, int x2, int y2){
this->line = &line;
this->x1 = x1;
this->y1 = y1;
this->x2 = x2;
this->y2 = y2;
}

int Triangle::calculateArea(){
return abs((x2 - x1)*(y2 - y1))/2;
}

int Triangle::calculatePerimeter(){
int a = abs(x2 - x1);
int b = abs(y2 - y1);
int c = (int)sqrt(a*a + b*b);
return a + b + c;
}

void Triangle::show(){
cout << "Triangle" << endl;
line->draw(x1, y1, x1, y2);
}

DotLine.cpp:

// 具体实现化角色

#include "../include/lines.h"
#include
#include
using namespace std;

void DotLine::draw(int x1, int y1, int x2, int y2){
cout << "drawDotLine" << x1 << "," << y1 << "," << x2 << "," << y2 << endl;
}

SolidLine.cpp:

// 具体实现化角色

#include "../include/lines.h"
#include
#include
using namespace std;

void SolidLine::draw(int x1, int y1, int x2, int y2){
cout << "drawSolidLine" << x1 << "," << y1 << "," << x2 << "," << y2 << endl;
}

Bridge.cpp
// 实现

//============================================================================
// Name : Bridge.cpp
// Author : Yan Chao
// Version :
// Copyright : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================


#include "../include/shape.h"
#include "../include/lines.h"


int main() {
int x1=0, y1=0, x2=1, y2=1;
Line *solidLine = new SolidLine();
Line *dotLine = new DotLine();
Shape *solidLineRectangle = new Rectangle(*solidLine,x1, y1, x2, y2);
Shape *dotLineRectangle = new Rectangle(*dotLine,x1, y1, x2, y2);
Shape *solidLineTriangle = new Triangle(*solidLine,x1, y1, x2, y2);
Shape *dotLineTriangle = new Triangle(*dotLine,x1, y1, x2, y2);

cout << "solidLineRectangle:" << endl;
solidLineRectangle->show();
cout << "dotLineRectangle:" << endl;
dotLineRectangle->show();
cout << "solidLineTriangle:" << endl;
solidLineTriangle->show();
cout << "dotLineTriangle:" << endl;
dotLineTriangle->show();

return 0;
}

输出结果:

solidLineRectangle:
Rectangle
drawSolidLine0,0,0,1
dotLineRectangle:
Rectangle
drawDotLine0,0,0,1
solidLineTriangle:
Triangle
drawSolidLine0,0,0,1
dotLineTriangle:
Triangle
drawDotLine0,0,0,1

0