Bridge定义 :
将抽象和行为划分开来,各自独立,但能动态的结合.
为什么使用?
通常,当一个抽象类或接口有多个具体实现,这些concrete之间关系可能有以下两种:
1. 这多个具体实现之间恰好是并列的,如前面举例,打桩,有两个concrete class:方形桩和圆形桩;这两个形状上的桩是并列的,没有概念上的重复,那么我们只要使用继承就可以了.
2.实际应用上,常常有可能在这多个concrete class之间有概念上重叠.那么需要我们把抽象共同部分和行为共同部分各自独立开来,原来是准备放在一个接口里,现在需要设计两个接口,分别放置抽象和行为.
例如,一杯咖啡为例,有中杯和大杯之分,同时还有加奶 不加奶之分. 如果用单纯的继承,这四个具体实现之间有概念重叠,因为有中杯加奶,也有中杯不加奶, 如果再在中杯这一层再实现两个继承,很显然混乱,扩展性极差.那我们使用Bridge模式来实现它.
如何实现?
以上面提到的咖啡 为例. 我们原来打算只设计一个接口,使用Bridge模式后,我们需要将抽象和行为分开,加奶和不加奶属于行为,我们将它们抽象成一个专门的行为接口:
public interface CoffeeImpl {
public String pourCoffeeImpl();
}
下面两个是行为的具体的实现子类
加奶
public class MilkCoffeeImpl implements CoffeeImpl {
public String pourCoffeeImpl() {
System.out.println("add milk");
return "add milk";
}
}
不加奶
public class FragrantCoffeeImpl implements CoffeeImpl {
public String pourCoffeeImpl() {
System.out.println("no milk");
return "no milk";
}
}
下面是咖啡的抽象父类,也就是区分大杯和中杯
public abstract class Coffee {
CoffeeImpl coffeeImpl;
public CoffeeImpl getCoffeeImpl() {
return coffeeImpl;
}
public void setCoffeeImpl(String way) {
this.coffeeImpl = ActionFactory.createCoffeeImpl(way);
}
public abstract void pourCoffee();
}
下面是2个抽象的具体实现子类
大杯
public class BigCoffee extends Coffee {
public BigCoffee(String way) {
pourCoffee();
this.setCoffeeImpl(way);
this.coffeeImpl.pourCoffeeImpl();
}
@Override
public void pourCoffee() {
System.out.print("Big coffee ");
}
}
中杯
public class MiddleCoffee extends Coffee {
public MiddleCoffee(String way) {
pourCoffee();
this.setCoffeeImpl(way);
this.coffeeImpl.pourCoffeeImpl();
}
@Override
public void pourCoffee() {
System.out.print("Middle coffee ");
}
}
下面是一个简单工厂,用来动态确定咖啡的行为,究竟是加奶还是不加奶,当然可以使用自己定义的方法来实现这个功能,这里我选择简单工厂。
public class ActionFactory {
public static CoffeeImpl createCoffeeImpl(String way) {
if("milk".equals(way)) {
return new MilkCoffeeImpl();
} else if("fragrant".equals(way)) {
return new FragrantCoffeeImpl();
} else {
return null;
}
}
}
到此为止,bridge模式就完成了,读者可以很方便的自己试试着这个基础上添加自己的咖啡抽象,比如小杯咖啡,还能添加咖啡行为,比如加糖不加糖,记得需要对简单工厂进行修改。
最后就是测试类
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
//中杯不加奶
Coffee coffee1 = new MiddleCoffee("fragrant");
//大杯加奶
Coffee coffee2 = new BigCoffee("milk");
//中杯加奶
Coffee coffee3 = new MiddleCoffee("milk");
//大杯不加奶
Coffee coffee4 = new BigCoffee("fragrant");
}
}
完成了,输出结果是:
Middle coffee no milk
Big coffee add milk
Middle coffee add milk
Big coffee no milk
可以看到调用很方便,类决定了什么样的咖啡(抽象),而参数决定了什么样的操作(行为)。