桥接模式
桥接(Bridge)是用于把抽象化与实现化解耦,使得二者可以独立变化。这种类型的设计模式属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。
这种模式涉及到一个作为桥接的接口,使得实体类的功能独立于接口实现类。这两种类型的类可被结构化改变而互不影响
桥接模式-不只改变你的实现,也改变你的抽象(把抽象化与实现化解耦,使得二者可以独立变化)
模式和结构定义
- 抽象角色(Abstraction): 抽象的定义,并保存一个Implementor对象的引用。
- 扩展抽象角色(RefineAbstraction): 拓展Abstraction。
- 抽象实现角色(Implementor): 定义实现类的接口,提供基本操作,其实现交给子类实现。
- 具体实现角色(ConcreteImplementor): 实现Implementor接口,在程序运行时,子类对象将替换其父类对象,提供给Abstraction具体的业务操作方法。
应用实例
模拟毛笔
现在需要提供大中小3种型号的画笔,能够绘制5种不同颜色,如果使用蜡笔,我们需要准备3*5=15支蜡笔,也就是说必须准备15个具体的蜡笔类。而如果使用毛笔的话,只需要3种型号的毛笔,外加5个颜料盒,用3+5=8个类就可以实现15支蜡笔的功能。本实例使用桥接模式来模拟毛笔的使用过程。
抽象对象
/**
* 毛笔抽象类
*
* @author shengyong.huang
* @date 2020-07-17
*/
public abstract class AbstractPen {
protected Color color;
public void setColor(Color color) {
this.color = color;
}
public abstract void draw(String name);
}
扩展抽象角色
/**
* @author shengyong.huang
* @date 2020-07-17
*/
public class SmallPen extends AbstractPen {
@Override
public void draw(String name) {
String penType = "小号毛笔绘制";
this.color.bepaint(penType, name);
}
}
/**
* @author shengyong.huang
* @date 2020-07-17
*/
public class MiddlePen extends AbstractPen {
@Override
public void draw(String name) {
String penType = "中号毛笔绘制";
this.color.bepaint(penType, name);
}
}
/**
* @author shengyong.huang
* @date 2020-07-17
*/
public class BigPen extends AbstractPen {
@Override
public void draw(String name) {
String penType = "大号毛笔绘制";
this.color.bepaint(penType, name);
}
}
抽象实现角色
/**
* 颜色接口
*
* @author shengyong.huang
* @date 2020-07-17
*/
public interface Color {
/**
* 填充颜色
*
* @param penType 笔类型
* @param name 名称
*/
void bepaint(String penType, String name);
}
具体实现角色
/**
* @author shengyong.huang
* @date 2020-07-17
*/
public class Black implements Color {
@Override
public void bepaint(String penType, String name) {
System.out.println(penType + "黑色的" + name + ".");
}
}
/**
* @author shengyong.huang
* @date 2020-07-17
*/
public class Blue implements Color
{
@Override
public void bepaint(String penType, String name)
{
System.out.println(penType + "蓝色的"+ name + ".");
}
}
/**
* @author shengyong.huang
* @date 2020-07-17
*/
public class Green implements Color {
@Override
public void bepaint(String penType, String name) {
System.out.println(penType + "绿色的" + name + ".");
}
}
/**
* @author shengyong.huang
* @date 2020-07-17
*/
public class Red implements Color {
@Override
public void bepaint(String penType, String name) {
System.out.println(penType + "红色的" + name + ".");
}
}
/**
* @author shengyong.huang
* @date 2020-07-17
*/
public class White implements Color {
@Override
public void bepaint(String penType, String name) {
System.out.println(penType + "白色的" + name + ".");
}
}
测试方法
/**
* @author shengyong.huang
* @date 2020-07-17
*/
public class TestMain {
public static void main(String[] args) {
AbstractPen smallPen = new SmallPen();
AbstractPen middlePen = new MiddlePen();
AbstractPen bigPen = new BigPen();
Color red = new Red();
Color blue = new Blue();
Color green = new Green();
smallPen.setColor(red);
smallPen.draw("鲜花");
middlePen.setColor(blue);
middlePen.draw("牛粪");
bigPen.setColor(green);
bigPen.draw("老黄牛");
}
}
测试结果
小号毛笔绘制红色的鲜花.
中号毛笔绘制蓝色的牛粪.
大号毛笔绘制绿色的老黄牛.
优点和不足
- 优点
- 抽象和实现的分离。
- 将实现予以结构,让它和界面之间不再永久绑定
- 抽象和实现可以独立扩展,不会影响到对方。
- 缺点
- 增加了系统的理解和设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计和编程。
- 要求正确识别出系统中两个独立变化的维度,因此其使用范围有一定的局限性。
使用场景
- 适合使用在需要跨越多个平台的图形和窗口系统上。
- 当需要用不同的方式改变接口和实现时,你会发现桥接模式很好用
- 对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用。
- 一个类存在两个独立变化的维度,且这两个维度都需要进行扩展;
补充
- 设计模式之桥梁模式和策略模式的区别
举一个例子:
策略模式:我要画圆,要实心圆,我可以用solidPen来配置,画虚线圆可以用dashedPen来配置。这是strategy模式。
桥接模式:同样是画圆,我是在windows下来画实心圆,就用windowPen+solidPen来配置,在unix下画实心圆就用unixPen+solidPen来配置。如果要再windows下画虚线圆,就用windowsPen+dashedPen来配置,要在unix下画虚线圆,就用unixPen+dashedPen来配置。
画圆方法中,策略只是考虑算法的替换,而桥接考虑的则是不同平台下需要调用不同的工具,接口只是定义一个方法,而具体实现则由具体实现类完成。
所以相对策略模式,桥接模式要表达的内容要更多,结构也更加复杂。
桥接模式表达的主要意义其实是接口隔离的原则,即把本质上并不内聚的两种体系区别开来,使得它们可以松散的组合,而策略在解耦上还仅仅是某一个算法的层次,没有到体系这一层次。
参考: