设计模式之桥接模式

2022-04-30  本文已影响0人  发现未知的自己

1 定义

桥接模式将抽象部分与它的实现部分分离,使它们可以独立地变化。或者也可以定义为:一个类存在两个(或多个)独立变化的维度,我们可以通过组合的方式,让这两个(或多个)维度可以独立进行扩展。

2 类图

桥接模式.png

3 伪代码实现

public abstract class Abstraction {
    protected Implementor implementor;
    
    public Abstraction(Implementor implementor) {
        this.implementor = implementor;
    }
    
    public abstract void operation();
}

public class RefinedAbstraction extends Abstraction {
    public void RefinedAbstraction(Implementor implementor) {
        super(implementor);
    }
    
    public void operation() {
        implementor.operationImpl();
    }
}

public interface Implementor {
    void operationImpl();
}

public class ConcreteImplementorA {
    public void operationImpl() {
        
    }
}

public class ConcreteImplementorB {
    public void operationImpl() {
        
    }
}

4 使用场景

假设有两个手机品牌M和N,两个品牌都有游戏和通讯录,从面向对象的角度来设计,如果采用继承的方式,我们会做如下设计:

c7661ca54385912394a7528aafe366fd.png

(引自大话设计模式)

3b91dbcc141f666276bd29fa1d555de9.png

(引自大话设计模式)

上面两种方式虽然采用了面向对象的设计方式,遵循了对修改关闭对扩展开放的设计原则,但是仔细想想,会出现什么问题?假设我们还有手机品牌H,I...,各类手机还有音乐软件、阅读软件等等其他软件,手机品牌和软件一组合,我们要编写的类就会出现指数级增长,这会导致系统越来越庞大,难以管理。

在这种情况下,我们就可以使用桥接模式,将继承改成组合的方式,增加一个手机品牌,我们只需增加一个品牌子类即可,增加一个软件,我们也只需增加一个类就行,新的手机品牌和新的软件功能只要组合起来就行了。

4.1 java代码

public interface IHandsetSoft {
    void run();
}

public class HandsetGame implements IHandsetSoft {
    @Override
    public void run() {
        System.out.println("运行手机游戏");
    }
}

public class HandsetAddressList implements IHandsetSoft {
    @Override
    public void run() {
        System.out.println("运行手机通讯录");
    }
}

public abstract class HandsetBrand {

    protected IHandsetSoft handsetSoft;

    public HandsetBrand(IHandsetSoft handsetSoft) {
        this.handsetSoft = handsetSoft;
    }

    public abstract void run();
}

public class HandsetBrandM extends HandsetBrand {
    public HandsetBrandM(IHandsetSoft handsetSoft) {
        super(handsetSoft);
    }

    @Override
    public void run() {
        System.out.println("手机品牌M");
        handsetSoft.run();
    }
}

public class HandsetBrandN extends HandsetBrand {
    public HandsetBrandN(IHandsetSoft handsetSoft) {
        super(handsetSoft);
    }

    @Override
    public void run() {
        System.out.println("手机品牌N");
        handsetSoft.run();
    }
}

public class Client {
    public static void main(String[] args) {
        // 手机游戏
        IHandsetSoft handsetGame = new HandsetGame();

        // 手机通讯录
        IHandsetSoft handsetAddressList = new HandsetAddressList();

        // 在手机品牌M上运行手机游戏
        HandsetBrand handsetBrandM = new HandsetBrandM(handsetGame);
        handsetBrandM.run();

        // 在手机品牌M上运行手机通讯录
        handsetBrandM = new HandsetBrandM(handsetAddressList);
        handsetBrandM.run();

        // 在手机品牌N上运行手机游戏
        HandsetBrand handsetBrandN = new HandsetBrandN(handsetGame);
        handsetBrandN.run();

        // 在手机品牌N上运行手机通讯录
        handsetBrandN = new HandsetBrandN(handsetGame);
        handsetBrandN.run();
    }
}

采用继承的方式,是一种紧耦合的方式,可以做扩展,但是比较困难,采用组合的方式是一种松耦合的方式,可以进行轻松的扩展。继承是is-a的关系,如果是is-a的关系,适合使用继承,组合是has-a的关系,如果是has-a的关系,适合使用组合。比如上面是手机上有手机游戏和手机通讯录,所以用组合更合适。
再比如红色长方形,绿色长方形,红色圆形,绿色圆形,可以理解为长方形或者原型具有红色或者绿色的属性,可以使用组合的方式。类图如下:

微信图片_20220430202617.png

(引自https://www.runoob.com/design-pattern/bridge-pattern.html)

上一篇下一篇

猜你喜欢

热点阅读