1.桥接模式的定义
将抽象部分有实现部分分离,使它们可以独立的进行变化。
2.桥接模式的使用场景
举例来说,假设现在需要为某个餐厅制造菜单,餐厅供应牛肉面、猪肉面…而且顾客可根据自己的口味选择是否添加辣椒。此时就产生了一个问题,如何应对这种变化:是否需要定义辣椒牛肉面、无辣牛肉面、辣椒猪肉面、无辣猪肉面四个子类?如果餐厅还供应羊肉面、韭菜面…呢?如果添加辣椒时可以选择无辣、微辣、中辣、重辣…风味呢?那程序岂非一直忙于定义子类?
为了解决这个问题,可以使用桥接模式,桥接模式的做法是把变化部分抽象出来,使变化部分与主类分离开来,从而将多个维度的变化彻底分离。最后提供一个管理类来组合不同维度上的变化,通过这种组合来满足业务的需要。
3.桥接模式的UML类图
4.桥接模式的实现
/**
* 风味接口:是否辣椒
* @author Administrator
*
*/
public interface Peppery {
String style();
}
/**
* 辣味风格
* @author Administrator
*
*/
public class PepperyStyle implements Peppery{
//实现辣味风格的方法
@Override
public String style() {
// TODO Auto-generated method stub
return "辣味很重,很过瘾...";
}
}
/**
* 不辣风格
* @author Administrator
*
*/
public class PlainStyle implements Peppery{
//实现不辣风格的方法
@Override
public String style() {
// TODO Auto-generated method stub
return "味道清淡,很养胃...";
}
}
/**
* 食材抽象类
* @author Administrator
*
*/
public abstract class AbstractNoodle {
//组合一个Peppery变量,用于将该维度的变化独立出来
protected Peppery style;
//每份Noodle必须组合一个Peppery对象
public AbstractNoodle(Peppery style) {
this.style = style;
}
public abstract void eat();
}
/**
* 猪肉面
* @author Administrator
*
*/
public class ProkyNoodle extends AbstractNoodle{
public ProkyNoodle(Peppery style) {
super(style);
}
//实现eat抽象方法
@Override
public void eat() {
// TODO Auto-generated method stub
System.out.println("这是一碗稍显油腻的猪肉面条"+super.style.style());
}
}
/**
* 牛肉面
* @author Administrator
*
*/
public class BeefNoodle extends AbstractNoodle{
public BeefNoodle(Peppery style) {
super(style);
// TODO Auto-generated constructor stub
}
//实现eat抽象方法
@Override
public void eat() {
// TODO Auto-generated method stub
System.out.println("这是一碗美味的牛肉面"+super.style.style());
}
}
/**
* 程序入口,测试桥接模式
* @author Administrator
*
*/
public class BridgeTest {
public static void main(String[] args) {
//下面将得到辣味牛肉面
AbstractNoodle noodle1 = new BeefNoodle(new PepperyStyle());
noodle1.eat();
//下面将得到不辣牛肉面
AbstractNoodle noodle2 = new BeefNoodle(new PlainStyle());
noodle2.eat();
//下面将得到辣味猪肉面
AbstractNoodle noodle3 = new ProkyNoodle(new PepperyStyle());
noodle3.eat();
//下面将得到不辣猪肉面
AbstractNoodle noodle4 = new ProkyNoodle(new PlainStyle());
noodle4.eat();
}
}
5.总结
桥接模式可以应用到许多开发中,但是它应用得却不多,一个很重要的原因是对于抽象与实现的分离的把握,是不是需要分离、如何分离?对设计者来说要有一个恰到好处的分寸。不管怎么说,桥接模式的优点我们毋庸置疑,分离抽象与实现、灵活的扩展以及对客户来说透明的实现等。但是使用桥接模式也有一个不明显的缺点,就是不容易设计,对开发者来说要有一定的经验要求。因此,对桥接模式应用来说,理解很简单,设计却不容易。
备注:读《Android源码设计模式解析与实践》笔记。