java设计模式之桥接模式

    定义:

    桥接(Bridge)是用于把抽象化与实现化解耦,使得二者可以独立变化。这种类型的设计模式属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。

    这种模式涉及到一个作为桥接的接口,使得实体类的功能独立于接口实现类。这两种类型的类可被结构化改变而互不影响。Bridge模式基于类的最小设计原则,通过使用封装,聚合以及继承等行为来让不同的类承担不同的责任。它的主要特点是把抽象(abstraction)与行为实现(implementation)分离开来,从而可以保持各部分的独立性以及应对它们的功能扩展。

解决问题:

    在有多种可能会变化的情况下,用继承会造成类爆炸问题,扩展起来不灵活。把这种多角度分类分离出来,让它们独立变化,减少它们之间耦合。

使用环境:

  • 如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系,通过桥接模式可以使它们在抽象层建立一个关联关系。
  • 抽象化角色和实现化角色可以以继承的方式独立扩展而互不影响,在程序运行时可以动态将一个抽象化子类的对象和一个实现化子类的对象进行组合,即系统需要对抽象化角色和实现化角色进行动态耦合。
  • 一个类存在两个独立变化的维度,且这两个维度都需要进行扩展。
  • 虽然在系统中使用继承是没有问题的,但是由于抽象化角色和具体化角色需要独立变化,设计要求需要独立管理这两者。对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用。

桥接模式UML图:

角色和职责:

    Abstraction:抽象类,抽象部分的接口。通常在这个对象里面,要维护一个实现部分的对象引用,在抽象对象里面的方法,需要调用实现部分的对象来完成。这个对象里面的方法,通常都是跟具体的业务相关的方法。

    RefinedAbstraction:扩充抽象类,扩展抽象部分的接口,通常在这些对象里面,定义跟实际业务相关的方法,这些方法的实现通常会使用Abstraction中定义的方法,也可能需要调用实现部分的对象来完成。

    Implementor:实现类接口,定义实现部分的接口,这个接口不用和Abstraction里面的方法一致,通常是由Implementor接口提供基本的操作,而Abstraction里面定义的是基于这些基本操作的业务方法,也就是说Abstraction定义了基于这些基本操作的较高层次的操作。

    ConcreteImplementor:具体实现类,真正实现Implementor接口的对象。

代码实现桥接模式示例:

/**
 * Implementor接口类
 */
public interface Engine {
	public void engine();
}
/*
 * ComImplementor接口实现类
 */
public class Engine2000 implements Engine{
	public void engine() {
		System.out.println("安装2000cc发动机");
	}
}

public class Engine2200 implements Engine{
	public void engine() {
		System.out.println("安装2200cc发动机");
	}
}
/**
 * Abstraction抽象类
 * @author Arain
 *
 */
public abstract class Car {
	private Engine engine;
	public Car(Engine engine){
		this.setEngine(engine);
	}
	public Engine getEngine() {
		return engine;
	}
	public void setEngine(Engine engine) {
		this.engine = engine;
	}
	
	public abstract void engine();
}
/**
 * RefinedAbstraction:扩充抽象类
 * @author Arain
 *
 */
public class Bus extends Car{

	public Bus(Engine engine) {
		super(engine);
	}

	@Override
	public void engine() {
		System.out.println("Bus:");
		this.getEngine().engine();
	}

}

public class Jeep extends Car{

	public Jeep(Engine engine) {
		super(engine);
	}

	@Override
	public void engine() {
		System.out.println("Jeep:");
		this.getEngine().engine();
	}

}

/**
 * Client测试类
 * @author Administrator
 *
 */
public class MainClass {
	public static void main(String[] args) {
		Car car = new Bus(new Engine2200());
		car.engine();
	}
}

    补充一个示例,感觉挺适合这个设计模式。日常购买交通票,我们可以从不同的平台购买,比如从12306官网,携程,飞猪等,同时可以购买不同的票中,比如高铁票,火车票,飞机票,可以选择不同的支付方式,不如微信,支付宝等。

代码如下:

/**
 * 支付方式
 * @author arain.liu
 * 2018年3月28日 下午9:02:46
 */
public abstract class Payment {
  public abstract void payment();
}
/**
 * 售票平台
 * @author arain.liu
 * 2018年3月28日 下午9:01:39
 */
public abstract class Provider {

  private Payment payment;
  
  public Provider(Payment payment){
    super();
    this.setPayment(payment);
  }
  
  public abstract void provider();

  public Payment getPayment() {
    return payment;
  }

  public void setPayment(Payment payment) {
    this.payment = payment;
  }
  
}
/**
 * 购买交通票
 * @author arain.liu
 * 2018年3月28日 下午8:59:46
 */
public abstract class Buy {

  private Provider provider;
  
  public Buy(Provider provider){
    super();
    this.setProvider(provider);
  }
  
  public abstract void buy();

  public Provider getProvider() {
    return provider;
  }

  public void setProvider(Provider provider) {
    this.provider = provider;
  }
}

/**
 * @author arain.liu
 * 2018年3月29日 下午12:31:17
 */
public class Elongprovider extends Provider {

  public Elongprovider(Payment payment) {
    super(payment);
  }

  @Override
  public void provider() {
    System.out.println("在艺龙下订单");
    this.getPayment().payment();
  }
}

/**
 * 携程
 * @author arain.liu
 * 2018年3月29日 下午12:28:54
 */
public class CtripProvider extends Provider {

  public CtripProvider(Payment payment) {
    super(payment);
  }

  @Override
  public void provider() {
    System.out.println("在携程下单");
    this.getPayment().payment();
  }

}
/**
 * 购买飞机票
 * @author arain.liu
 * 2018年3月29日 下午5:01:47
 */
public class BuyAirTicket extends Buy {
  public BuyAirTicket(Provider provider) {
    super(provider);
  }
  @Override
  public void buy() {
    System.out.println("购买飞机票");
    this.getProvider().provider();
  }
}
/**
 * 购买火车票
 * @author arain.liu
 * 2018年3月28日 下午9:16:21
 */
public class BuyTrainTicket extends Buy {
  public BuyTrainTicket(Provider provider) {
    super(provider);
  }
  @Override
  public void buy() {
    System.out.println("购买火车票");
    this.getProvider().provider();
  }
}

/**
 * 支付宝支付
 * @author arain.liu
 * 2018年3月29日 下午12:34:09
 */
public class AliPayment extends Payment {
  @Override
  public void payment() {
    System.out.println("支付宝支付");
  }
}
/**
 * 微信支付
 * @author arain.liu
 * 2018年3月29日 下午12:32:39
 */
public class WechatPayment extends Payment {
  @Override
  public void payment() {
    System.out.println("使用微信支付");
  }
}
/**
 * @author arain.liu
 * 2018年3月29日 下午12:34:48
 */
public class MainClass {
  public static void main(String[] args) {
  //加载支付方式
    Payment wp = new WechatPayment();
    Payment ap = new AliPayment();
    
    //加载供应商,配置不同的支付方式
    Provider ctripWp = new CtripProvider(wp);
    Provider ctripAp = new CtripProvider(ap);
    Provider elongWp = new Elongprovider(wp);
    Provider elongAp = new Elongprovider(ap);
    
    //加载购票种类,配置不同的供应商
    Buy buyTcw = new BuyTrainTicket(ctripWp);
    Buy buyTca = new BuyTrainTicket(ctripAp);
    Buy buyTew = new BuyTrainTicket(elongWp);
    Buy buyTea = new BuyTrainTicket(elongAp);
    
    Buy buyAcw = new BuyAirTicket(ctripWp);
    Buy buyAca = new BuyAirTicket(ctripAp);
    Buy buyAew = new BuyAirTicket(elongWp);
    Buy buyAea = new BuyAirTicket(elongAp);
    
    System.out.println("-------*******************-------");
    buyTcw.buy();
    System.out.println("-------*******************-------");
    buyTca.buy();
    System.out.println("-------*******************-------");
    buyTew.buy();
    System.out.println("-------*******************-------");
    buyTea.buy();
    System.out.println("-------*******************-------");
    buyAcw.buy();
    System.out.println("-------*******************-------");
    buyAca.buy();
    System.out.println("-------*******************-------");
    buyAew.buy();
    System.out.println("-------*******************-------");
    buyAea.buy();
    System.out.println("-------*******************-------");
  }
}

桥接模式优缺点:

优点:

    1、分离抽象接口及其实现部分。

    2、桥接模式有时类似于多继承方案,但是多继承方案违背了类的单一职责原则(即一个类只有一个变化的原因),复用性比较差,而且多继承结构中类的个数非常庞大,桥接模式是比多继承方案更好的解决方法。

    3、桥接模式提高了系统的可扩充性,在两个变化维度中任意扩展一个维度,都不需要修改原有系统。

    4、实现细节对客户透明,可以对用户隐藏实现细节。

缺点:

    1、桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。

    2、桥接模式要求正确识别出系统中两个独立变化的维度,因此其使用范围具有一定的局限性。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值