YAZONG 我的开源

设计模式(二十二)结构型模式(对象结构型模式)桥接模式-BRIDGE

 
0 评论0 浏览

定义

桥梁模式也叫做桥接模式。将抽象和实现解耦,使得两者可以独立地变化。

#彻底的解耦并没有什么意义。实现指的是抽象类和派生类用来实现自己的对象。

通用类图

image.png

#抽象角色引用实现角色,或者说抽象角色的部分实现是由实现角色完成的。

1)Abstraction-抽象化角色

它的主要职责是定义出该角色的行为,同时保存一个对实现化角色的引用,该角色一般是抽象类。

2)Implementor-实现化角色

它是接口或者抽象类,定义角色必需的行为和属性。

3)RefinedAbstraction

它引用实现化角色对抽象化角色进行修正。

4)ConcreteImplementor

它实现接口或抽象类定义的方法和属性。

通用案例

/**
 * 场景类
 */
public class Client1 {
    public static void main(String[] args) {
        //定义一个实现化角色
        Implementor implementor = new ConcreteImplementor1();
        //定义一个抽象化角色
        Abstraction abstraction = new RefinedAbstraction(implementor);
        //执行
        abstraction.request();
    }
}

/**
 * 实现化角色
 */
interface Implementor{
    //基本方法
    void doSomething();
    void doAnything();
}

/**
 * 具体实现化角色
 */
class ConcreteImplementor1 implements Implementor{
    @Override
    public void doSomething() {
        //业务逻辑处理
        System.out.println("ConcreteImplementor1-doSomething()");
    }

    @Override
    public void doAnything() {
        //业务逻辑处理
        System.out.println("ConcreteImplementor1-doAnything()");
    }
}

/**
 * 具体实现化角色
 */
class ConcreteImplementor2 implements Implementor{
    @Override
    public void doSomething() {
        //业务逻辑处理
        System.out.println("ConcreteImplementor2-doSomething()");
    }

    @Override
    public void doAnything() {
        //业务逻辑处理
        System.out.println("ConcreteImplementor2-doAnything()");
    }
}

/**
 * 抽象化角色
 */
abstract class Abstraction{
    //定义对实现化角色的引用
    private Implementor imp;
    //约束子类必须实现该构造函数
    public Abstraction(Implementor imp) {
        this.imp = imp;
    }
    //自身的行为和属性
    public void request(){
        this.imp.doSomething();
    }
    //获得实现化角色
    public Implementor getImp() {
        return imp;
    }
}

/**
 * 具体抽象化角色
 */
class RefinedAbstraction extends Abstraction{
    //覆写构造函数
    public RefinedAbstraction(Implementor imp) {
        super(imp);
    }
    //修正父类的行为
    @Override
    public void request() {
        /**
         * 业务处理....
         */
        super.request();
        super.getImp().doAnything();
    }
}

业务案例

案例1

image.png

/**
 * 场景类
 */
public class Client2 {
    public static void main(String[] args) {
        HouseCorp houseCorp = new HouseCorp();
        houseCorp.makeMoney();
        ClothesCorp clothesCorp = new ClothesCorp();
        clothesCorp.makeMoney();
    }
}

/**
 * 抽象公司
 */
abstract class Corp{
    abstract void produce();
    abstract void sell();
    public void makeMoney(){
        this.produce();
        this.sell();
    }
}

/**
 * 房地产公司
 */
class HouseCorp extends Corp{
    @Override
    void produce() {
        System.out.println("HouseCorp-produce()");
    }

    @Override
    void sell() {
        System.out.println("HouseCorp-sell()");
    }

    @Override
    public void makeMoney() {
        super.makeMoney();
    }
}

/**
 * 服装公司
 */
class ClothesCorp extends Corp{
    @Override
    void produce() {
        System.out.println("ClothesCorp-produce()");
    }

    @Override
    void sell() {
        System.out.println("ClothesCorp-sell()");
    }

    @Override
    public void makeMoney() {
        super.makeMoney();
    }
}

--
HouseCorp-produce()
HouseCorp-sell()
ClothesCorp-produce()
ClothesCorp-sell()

案例2

image.png

/**
 * 场景类
 */
public class Client3 {
    public static void main(String[] args) {
        HouseCorp houseCorp = new HouseCorp(new House());
        houseCorp.makeMoney();
        ShanZhaiCorp shanZhaiCorp = new ShanZhaiCorp(new IPod());
        shanZhaiCorp.makeMoney();
    }
}

/**
 * 抽象产品类
 */
abstract class Product{
    abstract void beProducted();
    abstract void beSelled();
}

/**
 * 房子
 */
class House extends Product{
    @Override
    void beProducted() {
        System.out.println("House-beProducted()");
    }
    @Override
    void beSelled() {
        System.out.println("House-beSelled()");
    }
}

/**
 * IPod
 */
class IPod extends Product{
    @Override
    void beProducted() {
        System.out.println("IPod-beProducted()");
    }
    @Override
    void beSelled() {
        System.out.println("IPod-beSelled()");
    }
}

/**
 * 抽象公司类
 */
abstract class Corp{
    //定义一个抽象产品对象,不知道具体是什么产品
    private Product product;
    //构造函数,由子类定义传递具体的产品进来
    public Corp(Product product) {
        this.product = product;
    }
    public void makeMoney(){
        //生产
        this.product.beProducted();
        //销售
        this.product.beSelled();
    }
}

/**
 * 房地产公司
 */
class HouseCorp extends Corp{
    public HouseCorp(House house) {
        super(house);
    }

    @Override
    public void makeMoney() {
        super.makeMoney();
    }
}

/**
 * 山寨公司
 */
class ShanZhaiCorp extends Corp{
    public ShanZhaiCorp(Product product) {
        super(product);
    }

    @Override
    public void makeMoney() {
        super.makeMoney();
    }
}

--
House-beProducted()
House-beSelled()
IPod-beProducted()
IPod-beSelled()

优点

1)抽象和实现抽离。

2)优秀的扩充能力。

3)实现细节对客户透明。

使用场景

#并不是一涉及继承就要考虑使用桥梁模式。桥梁模式的意图还是对变化的封装,尽量把可能变化的因素封装到最细、最小的逻辑单元中,避免风险扩散。

1)不希望或不适用使用继承的场景

例如继承层次过渡、无法更细化设计颗粒等场景,需要考虑使用桥梁模式。

继承是,一定要在是”is-a”的关系时再考虑使用,而不是任何时候都去使用。

2)接口或抽象类不稳定的场景

明知道接口不稳定还想通过实现或继承来实现业务需求,那是得不偿失的,也是比较失败的做法。

3)重用性要求较高的场景

设计的颗粒度越细,则被重用的可能性就越大,而采用继承则受父类的限制,不可能出现太细的颗粒度。

4)桥梁模式描述了类间弱关联关系。对于比较明确不发生变化的,则通过继承来完成;若不能确定是否会发生变化的,那就认为是会发生变化,则通过桥梁模式来解决。

合成/聚合复用原则

定义

合成/聚合复用原则(CARP),尽量/优先使用合成/聚合,尽量不要使用类继承。

通用类图

image.png

1)合成和聚合都是关联的特殊种类。聚合表示一种弱的”拥有”关系,体现的是A对象可以包含B对象,但B对象不是A对象的一部分;合成则是一种强的”拥有”关系,体现了严格的部分和整体的关系,部分和整体的生命周期一样。

2)优先使用对象的合成/聚合有助于你保持每个类被封装,并被集中在单个任务上。这样类和类继承层次会保持较小规模,并且不太可能增长为不可控制的庞然大物。

#学会用对象的职责(下述例子中的手机品牌或功能),而不是对象的结构来考虑问题

image.png

而不是

image.png


标题:设计模式(二十二)结构型模式(对象结构型模式)桥接模式-BRIDGE
作者:yazong
地址:https://blog.llyweb.com/articles/2020/12/14/1607876476250.html