桥接模式
概述
桥接模式:Decouple an abstraction from its implementation so that the two can vary independently.(将抽象和实现解耦,使得两者可以独立地变化。而不会直接影响到其他部分。
UML
-
Abstraction:
抽象部分的接口。通常在这个对象里面,要维护一个实现部分的对象引用,在抽象对象里面的方法,需要调用实现部分的对象来完成。这个对象里面的方法,通常都是跟具体的业务相关的方法。
-
RefinedAbstraction:
扩展抽象部分的接口,通常在这些对象里面,定义跟实际业务相关的方法,这些方法的实现通常会使用Abstraction中定义的方法,也可能需要调用实现部分的对象来完成。
-
Implementor:
定义实现部分的接口,这个接口不用和Abstraction里面的方法一致(根据约定优于配置原则,建议跟Abstraction一致。),通常是由Implementor接口提供基本的操作,而Abstraction里面定义的是基于这些基本操作的业务方法,也就是说Abstraction定义了基于这些基本操作的较高层次的操作。
-
ConcreteImplementor:
真正实现Implementor接口的对象。
使用场景:
● 不希望或不适用使用继承的场景
● 接口或抽象类不稳定的场景
● 重用性要求较高的场景
示例
未使用桥接模式的抽象与实现结构图(如下):
如果要增加一个apple品牌的电脑,则需要在台式机下新增一个apple的台式机
在笔记本下新增一个apple笔记本,在pad下新增一个apple的pad。代码比较繁琐。
如果使用桥接模式(如下图),使抽象部分和抽象的派生(实现)部分分离出来,这样让它们各自的变化,这样每种实现就不会影响到其他实现。从而达到对应变化的目的
将电脑类型作为一个维度,将品牌也做为一个维度。两个维度独立起来,可以任意的变化。
桥接模式解决了多层继承的结构,处理多维度变化的场景,将各个维度设计成独立的继承结构。使各个维度可以独立的扩展在抽象层建立联系。
package com.dyleaf.structure.BridgePattern;
public interface ImplementorBrand {
public void sale();
}
class ConcreteImplementorAcer implements ImplementorBrand{
@Override
public void sale() {
System.out.println("宏碁品牌");
}
}
class ConcreteImplementorApple implements ImplementorBrand{
@Override
public void sale() {
System.out.println("苹果品牌");
}
}
class ConcreteImplementorDell implements ImplementorBrand{
@Override
public void sale() {
System.out.println("戴尔品牌");
}
}
package com.dyleaf.structure.BridgePattern;
public class AbstractionComputer {
protected ImplementorBrand brand;
public AbstractionComputer(ImplementorBrand brand){
this.brand=brand;
}
public void sale(){
brand.sale();
}
}
/**
* 扩展部分
*/
class RefinedAbstractionDesktop extends AbstractionComputer{
public RefinedAbstractionDesktop(ImplementorBrand brand) {
super(brand);
}
@Override
public void sale() {
//添加自己的特性,实际业务。
paly();
super.sale();
}
public void paly(){
System.out.println("我台式机抗摔打");
}
}
class RefinedAbstractionLaptop extends AbstractionComputer{
public RefinedAbstractionLaptop(ImplementorBrand brand) {
super(brand);
}
@Override
public void sale() {
//添加自己的特性,实际业务。
lighting();
super.sale();
}
public void lighting(){
System.out.println("我笔记本电脑充电5分钟,续航5小时");
}
}
class RefinedAbstractionPad extends AbstractionComputer{
public RefinedAbstractionPad(ImplementorBrand brand) {
super(brand);
}
@Override
public void sale() {
//添加自己的特性,实际业务。
weighting();
super.sale();
}
public void weighting(){
System.out.println("我平板电脑便于携带");
}
}
优缺点
- 不同对象间的组合产生不同的结果,将抽象和实现进行分离,当然,如果要扩展功能的,只要实现相应的接口,继承对应的类。就可以。
- 把抽象(abstraction)与行为实现(implementation)分离开来,从而可以保持各部分的独立性以及应对它们的功能扩展