桥接模式
定义
将抽象部分与它的实现部分分离,使它们都可以独立地变化。
实现系统可能有多角度分类,每一种都有可能变化,那么就把这种多角度分离出来独立变化,减少它们之间的耦合。
解决
在有多种可能会变化的情况下,用继承会造成类爆炸问题,扩展起来不灵活。
优点
- 分离抽象接口及其实现部分。
- 桥接模式有时类似于多继承方案,但是多继承方案违背了类的单一职责原则(即一个类只有一个变化的原因),复用性比较差,而且多继承结构中类的个数非常庞大,桥接模式是比多继承方案更好的解决方法。
- 桥接模式提高了系统的可扩充性,在两个变化维度中任意扩展一个维度,都不需要修改原有系统。
- 实现细节对客户透明,可以对用户隐藏实现细节。
缺点
- 桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。桥接模式要求正确识别出系统中两个独立变化的维度,因此其使用范围具有一定的局限性。
结构
桥接模式包含如下角色:
- Abstraction:抽象类
- RefinedAbstraction:扩充抽象类
- Implementor:实现类接口
- ConcreteImplementor:具体实现类
实现
package bridgemethod;
public abstract class Implementor {
public abstract void operation();
}
class ConcreteImplemtorA extends Implementor {
@Override
public void operation() {
System.out.println("ConcreteImplemtorA的方法执行");
}
}
class ConcreteImplemtorB extends Implementor {
@Override
public void operation() {
System.out.println("ConcreteImplemtorB的方法执行");
}
}
package bridgemethod;
public abstract class Abstraction {
//Abstraction聚合Implementor
protected Implementor implementor;
public void setImplementor(Implementor implementor) {
this.implementor = implementor;
}
public abstract void operation();
}
abstract class RefineAbstraction extends Abstraction
{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public RefineAbstraction(String name) {
this.setName(name);
}
@Override
public void operation() {
System.out.print("Abstraction-" + this.getName() + ": ");
implementor.operation();
}
}
class AbstractionA extends RefineAbstraction {
@Override
public void operation() {
super.operation();
}
public AbstractionA(String name) {
super(name);
}
}
class AbstractionB extends RefineAbstraction {
@Override
public void operation() {
super.operation();
}
public AbstractionB(String name) {
super(name);
}
}
package bridgemethod;
public class BridgeClient {
public static void main(String[] args) {
Abstraction a = new AbstractionA("A");
a.setImplementor(new ConcreteImplemtorA());
a.operation();
a.setImplementor(new ConcreteImplemtorB());
a.operation();
Abstraction b = new AbstractionB("B");
b.setImplementor(new ConcreteImplemtorA());
b.operation();
b.setImplementor(new ConcreteImplemtorB());
b.operation();
//这样多个扩充抽象类和多个具体实现类,能够复杂的混合在一起
//多角度的分类每一种都有变化的系统,将多角度分类抽象出来,减少他们的耦合
}
}
实例
大话设计模式中是手机品牌和软件的不同不能同一端玩游戏(因为软件是属于品牌自家的)。我觉得现在的话例子不是太好。换一个例子。
这里例子:两种品牌车和两种动力方式组合,进行桥接模式学习。
package bridgemethod.demo;
//抽象类
public abstract class Car {
protected Engine engine;
public Car(Engine engine)
{
this.engine=engine;
}
public abstract void drive();
}
//修正抽象类,增加一些功能
abstract class RefinedCar extends Car{
public RefinedCar(Engine engine) {
super(engine);
}
public abstract String getBrand();
public void drive()
{
this.engine.start();
System.out.println("开"+getBrand()+"车");
}
}
class BCar extends RefinedCar {
public BCar(Engine engine) {
super(engine);
}
public String getBrand() {
return "B";
}
}
class ACar extends RefinedCar {
public ACar(Engine engine) {
super(engine);
}
public String getBrand() {
return "A";
}
}
package bridgemethod.demo;
public interface Engine {
void start();
}
class GasolineEngine implements Engine {
public void start() {
System.out.print("Start Gasoline Engine...");
}
}
class ElectricEngine implements Engine {
public void start() {
System.out.print("Start Electric Engine...");
}
}
package bridgemethod.demo;
public class BridgeClient {
public static void main(String[] args) {
RefinedCar ag=new ACar(new GasolineEngine());
RefinedCar ae=new ACar(new ElectricEngine());
RefinedCar bg=new BCar(new GasolineEngine());
RefinedCar be=new BCar(new ElectricEngine());
ag.drive();
ae.drive();
bg.drive();
be.drive();
}
}
总结
桥接模式将抽象部分与它的实现部分分离,使它们都可以独立地变化。它是一种对象结构型模式,又称为柄体(Handle and Body)模式或接口(Interface)模式。
- 桥接模式包含如下四个角色:抽象类中定义了一个实现类接口类型的对象并可以维护该对象;扩充抽象类扩充由抽象类定义的接口,它实现了在抽象类中定义的抽象业务方法,在扩充抽象类中可以调用在实现类接口中定义的业务方法;实现类接口定义了实现类的接口,实现类接口仅提供基本操作,而抽象类定义的接口可能会做更多更复杂的操作;具体实现类实现了实现类接口并且具体实现它,在不同的具体实现类中提供基本操作的不同实现,在程序运行时,具体实现类对象将替换其父类对象,提供给客户端具体的业务操作方法。
- 在桥接模式中,抽象化(Abstraction)与实现化(Implementation)脱耦,它们可以沿着各自的维度独立变化。
- 桥接模式的主要优点是分离抽象接口及其实现部分,是比多继承方案更好的解决方法,桥接模式还提高了系统的可扩充性,在两个变化维度中任意扩展一个维度,都不需要修改原有系统,实现细节对客户透明,可以对用户隐藏实现细节;其主要缺点是增加系统的理解与设计难度,且识别出系统中两个独立变化的维度并不是一件容易的事情。
- 桥接模式适用情况包括:需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系;抽象化角色和实现化角色可以以继承的方式独立扩展而互不影响;一个类存在两个独立变化的维度,且这两个维度都需要进行扩展;设计要求需要独立管理抽象化角色和具体化角色;不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统。