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,1area:1perimeter:4########################dotLineRectangle:This is an Rectangle!drawSolidLine:0,0,1,1area:1perimeter:4########################solidLineTriangle:This is an Triangle!drawDotLine:0,0,1,1area:0perimeter:3########################dotLineTriangle:This is an Triangle!drawSolidLine:0,0,1,1area:0perimeter:3
C++:
shape.h(定义在include包中):
// 抽象化角色
#ifndef SHAPE_H_
#define SHAPE_H_#include "lines.h"#include <iostream>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 <stdlib.h>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 <stdlib.h>#include <math.h>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 <stdlib.h>#include <iostream>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 <stdlib.h>#include <iostream>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:
RectangledrawSolidLine0,0,0,1dotLineRectangle:RectangledrawDotLine0,0,0,1solidLineTriangle:TriangledrawSolidLine0,0,0,1dotLineTriangle:TriangledrawDotLine0,0,0,1