桥接模式:将抽象和实现放在两个不同的类层次中,使它们可以独立地变化。
这个模式比较难理解,但是我们只要通过例子来说明,相信还是可以理解清楚的。
1、桥接中的具体角色介绍
类的功能层次结构:父类具有基本功能,在子类中增加新的功能;
类的实现层次结构:父类通过声明抽象方法来定义接口,子类通过实现具体方法来实现接口;
桥接(Bridge)模式包含以下主要角色。
抽象化(Abstraction)角色:使用实现者角色提供的接口来定义基本功能接口。持有实现者角色,并在功能接口中委托给它,起到搭建桥梁的作用;注意,抽象化角色并不是指它就是一个抽象类,而是指抽象了实现。
扩展抽象化(Refined Abstraction)角色:是抽象化角色的子类,实现父类中的业务方法,并通过组合关系调用实现化角色中的业务方法。
实现化(Implementor)角色:定义实现化角色的接口,供扩展抽象化角色调用。
具体实现化(Concrete Implementor)角色:给出实现化角色接口的具体实现。
如果抽象和实现两者做不到独立地变化,就不算桥接模式。
2、为什么要用桥接模式
这里举个例子,加入我们要生产正方形和圆形,假如要生产红色的正方形,黄色的正方形,红色的圆形,黄色的圆形,那么这里就要有四个类,试想一下,假如我们有100个形状要生产,此时每增加一种颜色,就必须加100个不同形状的类。颜色和形状耦合的太厉害。最终会导致类爆炸。也可以举另一个例子,生产一批手机,和一批软件,如果软件和手机耦合的太死,那么每生产一个软件,都要新建对应数量的手机实现类。这样最终也会导致类爆炸。
此时如果我们用桥接模式,让抽象也就是形状和实现也就是颜色分开来,那么久不用担心啦。下面用桥接模式生产不同颜色的形状为例子。
3、UML
Shade是抽象化角色,CircleShade和SquareShade是扩展抽象化角色,Color是实现化角色,YelloColor和RedColor是具体实现化角色,如图的桥接模式实现了抽象和实现独立变化,所以称得上是桥接模式,我觉得叫这个名字也可能是UML图像一座桥。不管是增加抽象和增加实现,互不影响,这样子就不会导致类爆炸。
4、实现化角色Color
/**
* 实现化角色
* 画颜色
* @author suibibk.com
*
*/
public interface Color {
public void paint();
}
5、具体实现化角色:YelloColor和RedColor
/**
* 具体实现化角色
* @author suibibk.com
*/
public class YelloColor implements Color {
@Override
public void paint() {
System.out.println("黄色");
}
}
/**
* 具体实现化角色
* @author suibibk.com
*/
public class RedColor implements Color {
@Override
public void paint() {
System.out.println("红色");
}
}
6、抽象化角色Shade
/**
* 抽象化角色
* 形状
* @author suibibk.com
*/
public abstract class Shade {
protected Color color;
public void setColor(Color color) {
this.color = color;
}
public Color getColor() {
return color;
}
public abstract void draw();
}
7、扩展抽象化角色:CircleShade和SquareShade
/**
* 扩展抽象化角色
* @author suibibk.com
*/
public class CircleShade extends Shade{
@Override
public void draw() {
System.out.println("开始画圆形,确定颜色");
color.paint();
System.out.println("画圆形结束");
}
}
/**
* 扩展抽象化角色
* @author suibibk.com
*/
public class SquareShade extends Shade{
@Override
public void draw() {
System.out.println("开始画正方形,确定颜色");
getColor().paint();
System.out.println("正方形结束");
}
}
8、测试类Test
public class Test {
public static void main(String[] args) {
//画一个红色的圆形
Shade shade1 = new CircleShade();
shade1.setColor(new RedColor());
shade1.draw();
//画一个黄色的圆形
Shade shade2 = new CircleShade();
shade2.setColor(new YelloColor());
shade2.draw();
//画一个红色的正方形
Shade shade3 = new SquareShade();
shade3.setColor(new RedColor());
shade3.draw();
//画一个黄色的正方形
Shade shade4 = new SquareShade();
shade4.setColor(new YelloColor());
shade4.draw();
}
}
运行测试类,将输出如下结果:
开始画圆形,确定颜色
红色
画圆形结束
开始画圆形,确定颜色
黄色
画圆形结束
开始画正方形,确定颜色
红色
正方形结束
开始画正方形,确定颜色
黄色
正方形结束
到此用桥接模式实现了形状和颜色分离,独自变化,如果以后新加一个颜色,并不需要改动抽象化的代码,如果加入一个形状也不需要改动颜色的代码。
9、优缺点
优点:a、抽象和实现的分离。 b、优秀的扩展能力。 c、实现细节对客户透明。
缺点:桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。
10、桥接模式通常适用于以下场景:
当一个类存在两个独立变化的维度,且这两个维度都需要进行扩展时。
当一个系统不希望使用继承或因为多层次继承导致系统类的个数急剧增加时。
当一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性时。
总结
桥接模式,相对于之前学过的那些模式来说是比较难理解一点,但是我相信通过上面的实例,应该会理解的。主要要理解一句话也就是桥接模式的定义:将抽象和实现放在两个不同的类层次中,使它们可以独立地变化。