一、介绍,定义
又称桥梁模式,结构型设计模式。
承接者连接 两边 的作用,两边指抽象部分和实现部分。
将 抽象部分 和 实现部分 分离,使它们都可以独立地进行变化。
二、使用场景
对于不希望使用继承或因多层次继承导致系统类的个数急剧增加的系统,考虑使用桥接模式。
需要在构件的抽象化角色和具体角色之间增加更多灵活性,避免两层次间建立静态的继承关系,可通过桥接模式使它们在抽象层建立一个关联关系。
一个类存在两个独立变化的维度,且这两个维度都需进行扩展。
任何多维度变化类或多个树状类之间的耦合可通过桥接模式解耦。
三、UML类图
四、通用代码
Abstraction:抽象部分该类保持一个对实现部分对象的引用,抽象部分中的方法需要调用实现部分的对象来实现。该类一般为抽象类。
RefinedAbstraction:优化的抽象部分抽象部分的具体实现,该类一般是对抽象部分的方法进行完善和扩展。
Implementor:实现部分可以为接口或抽象类,其方法不一定要与抽象部分中的一致,一般情况下是由实现部分提供基本的操作,而抽象部分定义的则是基于实现部分这些基本操作的业务方法。
ConcreteImplementorA/B:实现部分的具体实现完成实现部分中定义的具体逻辑。
// 实现部分的抽象接口
public interface Implementor {
/** * 实现抽象部分的具体方法 */
public void operationImpl();
}
// 实现部分具体的实现
public class ConcreteImplementorA implements Implementor {
@Override
public void operationImpl() {
// 忽略实现逻辑
}
}
// 抽象部分
public abstract class Abstraction {
// 声明一私有成员变量引用实现部分的对象
private Implementor mImplementor;
/** * 通过实现部分对象的引用构造抽象部分的对象 *
@param implementor 实现部分对象的引用 */
public Abstraction(Implementor implementor) {
mImplementor = implementor;
}
/** * 通过调用实现部分具体的方法实现具体的功能 */
public void operation() {
mImplementor.operationImpl();
}
}
// 优化的抽象部分
public class RefinedAbstraction extends Abstraction {
public RefinedAbstraction(Implementor implementor) {
super(implementor);
}
/** * 对 Abstraction 中的方法进行扩展 */
public void refinedOperation() {
// 忽略实现逻辑
}
}
// 客户端实现
public class Client {
public static void main(String[] args) {
RefinedAbstraction abstration = new RefinedAbstraction( new ConcreteImplementorA );
abstraction.operation();
abstraction.refinedOperation();
}
}
五、简单实现
大家都知道去喝咖啡一般分为四种。大杯加糖,大杯不加糖,小贝加糖,小杯不加糖,对于一杯咖啡来说这4中就是两种变化,一种是大杯与小杯,加糖与不加糖,这两种变化胡良独立变化。这里就可以用桥接模式。
这里的Coffee.java代表抽象部分Abstraction
public abstract class Coffee {
protected CoffeeAddttives addttives;
public Coffee(CoffeeAddttives addttives) {
super();
this.addttives = addttives;
}
public abstract void makeCoffee();
}
LargeCoffee,SmallCoffee代表 RefinedAbstraction优化的抽象部分
public class LargeCoffee extends Coffee {
public LargeCoffee(CoffeeAddttives addttives) {
super(addttives);
}
@Override
public void makeCoffee() {
System.out.println("小杯的" + addttives.addSomething() + "咖啡");
}
}
public class SmallCoffee extends Coffee {
public SmallCoffee(CoffeeAddttives addttives) {
super(addttives);
}
@Override
public void makeCoffee() {
System.out.println("大杯的" + addttives.addSomething() + "咖啡");
}
}
CoffeeAddttives也就是Implementor角色,实现部分的抽象接口
/**
* 咖啡添加剂 往咖啡添加糖或者原味
*/
public abstract class CoffeeAddttives {
public abstract String addSomething();
}
Sugar、Ordinary也就是ConcreImplementor角色,
public class Ordinary extends CoffeeAddttives {
@Override
public String addSomething() {
return "原味";
}
}
public class Sugar extends CoffeeAddttives {
@Override
public String addSomething() {
return "加糖";
}
}
客户端
public class Client {
public static void main(String[] args) {
//准备原味
Ordinary ordinary = new Ordinary();
//准备糖
Sugar sugar = new Sugar();
//原味大杯
LargeCoffee largeCoffee = new LargeCoffee(ordinary);
largeCoffee.makeCoffee();
//加糖大杯
largeCoffee = new LargeCoffee(sugar);
largeCoffee.makeCoffee();
//原味小杯
SmallCoffee smallCoffee = new SmallCoffee(ordinary);
smallCoffee.makeCoffee();
//加糖小杯
smallCoffee = new SmallCoffee(sugar);
smallCoffee.makeCoffee();
}
}
小杯的原味咖啡
小杯的加糖咖啡
大杯的原味咖啡
大杯的加糖咖啡
这里的CoffeeAddttives对应的是UML类图中的实现部分也就是Implementor角色,而Coffee对应抽象部分,也就是Abstraction角色。
另外模式中定义的“抽象”与“实现”实质上对应的两个独立变化为 维护,所以上文才说任何维度辩护A类或者说多个树状类之间的耦合都可以使用桥接模式来实现解耦。
这里使用桥接模式也就是将是否加糖与大小杯两个维度实现了解耦。
此时如果我们想加个中杯的咖啡,只需要添加一个类
public class MiddleCoffee extends Coffee {
public MiddleCoffee(CoffeeAddttives addttives) {
super(addttives);
// TODO Auto-generated constructor stub
}
@Override
public void makeCoffee() {
System.out.println("中杯的" + addttives.addSomething() + "咖啡");
}
}
客户端稍作修改即可。添加以下代码
//原味小杯
MiddleCoffee middleCoffee = new MiddleCoffee(ordinary);
middleCoffee.makeCoffee();
//加糖小杯
middleCoffee = new MiddleCoffee(sugar);
middleCoffee.makeCoffee();
简单实现2
苹果、联想、戴尔 都有 平板、笔记本、台式机
由图可见,继承关系复杂,要新增一个需要在每个下面都分别添加,违反单一原则
建立品牌类接口
public interface Brand{
void info();
}
各个具体品牌:
//联想
public class Lenovo implements Brand{
@Override
public void info(){
System.out.println("联想");
}
}
//苹果
public class Apple implements Brand{
@Override
public void info(){
System.out.println("苹果");
}
}
...
以抽象的电脑类为例
public abstract class Computer{
//组合、品牌
protected Brand brand;
public Compluter (Brand brand){
this.brand = brand;
}
public void info(){
brand.info(); //品牌
}
}
具体的桌面电脑
class Desktop extends Computer{
public Desktop(Brand){
super.info();
}
@Override
public void info(){
super.info();
System.out.println("台式机");
}
}
测试类
puvlic class Test{
public static void main(String []args){
Computer computer = new Laptop(new Apple());
computer.info();
}
}
computer增加不会影响品牌类
类图(对比上面的图):
六、模式的优缺点:
桥接模式,分离抽象与实现,其优点毋庸置疑,即灵活的扩展以及对客户来说透明的是实现。但不足之处在于运用桥接模式进行设计,是有一定难度的,需多加推敲与研究。