Bridge模式的目的:把抽象部分和行为部分分离,使它们都能独立变化。
任何事物对象都有抽象和行为之分,例如人,人是一种抽象,人分男人和女人等;人有行为,行为也有各种具体表现,所以,“人”与“人的行为”两个概念也反映了抽象和行为之分。
在面向对象设计的基本概念中,对象这个概念实际是由属性和行为两个部分组成的,属性我们可以认为是一种静止的,是一种抽象,一般情况下,行为是包含在一个对象中,但是,在有的情况下,我们需要将这些行为也进行归类,形成一个总的行为接口,这就是桥模式的用处。
总之,Bridge模式就是使抽象和行为分离,做到各自的独立发展,就是说抽象和行为各抽象出一个接口。当需要扩展行为或者抽象部分时,
只需扩展相应部分,而不用修改原来的结构。
例子一:
假如有个类DrawGraph有个画圆的接口,当然这个圆形可以用铅笔画,也可以用钢笔画。其中画圆是抽象部分,
用铅笔画和用钢笔画是行为部分。往往这个时候我们分别会定义铅笔类PencilDraw,钢笔类PenDraw来实现Draw,
这样就使得抽象部分和行为部分固定的捆绑在一起,扩展性不强。假如要动态增加一个用粉笔画的行为和一个画方形的抽象部分,
就必然要新定义一个ChalkDraw类,DrawGraph类里增加drawRectangle接口。显然这是很麻烦的。
Bridge模式是这样实现的:
//抽象部分
public abstract class DrawGraph {
private ToolDraw toolDraw;
public void setToolDraw(){
this.toolDraw = ToolDrawSingleton.getToolDraw();//用Singleton模式来选工具。
}
public ToolDraw getToolDraw(){
return toolDraw;
}
public abstract void draw();
}
//画圆
public class DrawCircle implements DrawGraph{
public DrawCircle(){
setToolDraw();
}
public void draw(){
System.out.pritnln(toolDraw.getName() + " draw circle");
}
}
//画矩形
public class DrawRectangle implements DrawGraph{
public DrawRectangle(){
setToolDraw();
}
public void draw(){
System.out.pritnln(toolDraw.getName() + " draw rectangle");
}
}
//行为部分
public abstract class ToolDraw{
public abstract String getName();
public abstract void drawWithTool();
}
//铅笔
public class PencilDraw implements ToolDraw{
private final static String name = "Pencil";
public static String getName(){
return name;
}
public void drawWithTool(){
System.out.println("Draw with Pencil.");
}
}
//钢笔
public class PenDraw implements ToolDraw{
private final static String name = "Pen";
public String getName(){
return name;
}
public void drawWithTool(){
System.out.println("Draw with Pen.");
}
}
//粉笔
public class ChalkDraw implements ToolDraw{
private final static String name = "Chalk";
public String getName(){
return name;
}
public void drawWithTool(){
System.out.println("Draw with Chalk.");
}
}
做一个Singleton类来联系抽象和行为。通过此类来选工具
public class ToolDrawSingleton{
private static ToolDraw toolDraw;
public ToolDrawSingleton(ToolDraw toolDraw){
this.toolDraw = toolDraw
}
public static ToolDraw getToolDraw(){
return toolDraw;
}
}
假如我们现在要用粉笔来画一个方形,一个圆形:
//取得工具
ToolDrawSingleton tool = new ToolDrawSingleton(new ChalkDraw());
//画方形
DrawGraph drawRectangle = new DrawRectangle();
drawRectangle.draw();
//画圆形
drawRectangle = new DrawCircle();
drawRectangle.draw();
例子二:
例如,一杯咖啡为例,子类实现类为四个:中杯加奶、大杯加奶、 中杯不加奶、大杯不加奶。
但是,我们注意到:上面四个子类中有概念重叠,可从另外一个角度进行考虑,这四个类实际是两个角色的组合:抽象 和行为,其中抽象为:中杯和大杯;行为为:加奶 不加奶(如加橙汁 加苹果汁).
实现四个子类在抽象和行为之间发生了固定的绑定关系,如果以后动态增加加葡萄汁的行为,就必须再增加两个类:中杯加葡萄汁和大杯加葡萄汁。显然混乱,扩展性极差。
那我们从分离抽象和行为的角度,使用Bridge模式来实现。
如何实现?
以上面提到的咖啡 为例. 我们原来打算只设计一个接口(抽象类),使用Bridge模式后,我们需要将抽象和行为分开,加奶和不加奶属于行为,我们将它们抽象成一个专门的行为接口.
先看看抽象部分的接口代码:
public abstract class Coffee { CoffeeImp coffeeImp;
public void setCoffeeImp() { this.CoffeeImp = CoffeeImpSingleton.getTheCoffeImp(); }
public CoffeeImp getCoffeeImp() {return this.CoffeeImp;}
public abstract void pourCoffee(); }
|
其中CoffeeImp 是加不加奶的行为接口,看其代码如下:
public abstract class CoffeeImp { public abstract void pourCoffeeImp(); }
|
现在我们有了两个抽象类,下面我们分别对其进行继承,实现concrete class:
//中杯 public class MediumCoffee extends Coffee { public MediumCoffee() {setCoffeeImp();}
public void pourCoffee() { CoffeeImp coffeeImp = this.getCoffeeImp(); //我们以重复次数来说明是冲中杯还是大杯 ,重复2次是中杯 for (int i = 0; i < 2; i++) {
coffeeImp.pourCoffeeImp(); } } }
//大杯 public class SuperSizeCoffee extends Coffee { public SuperSizeCoffee() {setCoffeeImp();}
public void pourCoffee() { CoffeeImp coffeeImp = this.getCoffeeImp(); //我们以重复次数来说明是冲中杯还是大杯 ,重复5次是大杯 for (int i = 0; i < 5; i++) {
coffeeImp.pourCoffeeImp(); } } }
|
上面分别是中杯和大杯的具体实现.下面再对行为CoffeeImp进行继承:
//加奶 public class MilkCoffeeImp extends CoffeeImp { MilkCoffeeImp() {}
public void pourCoffeeImp() { System.out.println("加了美味的牛奶"); } }
//不加奶 public class FragrantCoffeeImp extends CoffeeImp { FragrantCoffeeImp() {}
public void pourCoffeeImp() { System.out.println("什么也没加,清香"); } }
|
Bridge模式的基本框架我们已经搭好了,别忘记定义中还有一句:动态结合,我们现在可以喝到至少四种咖啡:
1.中杯加奶
2.中杯不加奶
3.大杯加奶
4.大杯不加奶
看看是如何动态结合的,在使用之前,我们做个准备工作,设计一个单态类(Singleton)用来hold当前的CoffeeImp:
public class CoffeeImpSingleton { private static CoffeeImp coffeeImp;
public CoffeeImpSingleton(CoffeeImp coffeeImpIn) {this.coffeeImp = coffeeImpIn;}
public static CoffeeImp getTheCoffeeImp() { return coffeeImp; } }
|
看看中杯加奶 和大杯加奶 是怎么出来的:
//拿出牛奶
CoffeeImpSingleton coffeeImpSingleton = new CoffeeImpSingleton(new MilkCoffeeImp());
//中杯加奶
MediumCoffee mediumCoffee = new MediumCoffee();
mediumCoffee.pourCoffee();
//大杯加奶
SuperSizeCoffee superSizeCoffee = new SuperSizeCoffee();
superSizeCoffee.pourCoffee();
注意: Bridge模式的执行类如CoffeeImp和Coffee是一对一的关系, 正确创建CoffeeImp是该模式的关键。
posted on 2006-07-10 17:13
保尔任 阅读(397)
评论(0) 编辑 收藏 所属分类:
Design Patten