桥接模式——合成/聚合复用原则的最佳实践

目录

一、基础简介

1、定义

2、使用场景

3、优缺点

4、模式结构分析

二、实例实现

1、实例场景分析

2、Abstraction(抽象类)

3、RefinedAbstraction(扩充抽象类)

4、Implementor(实现类接口)

5、ConcreteImplementor(具体实现类)

6、客户端

7、结果展示


一、基础简介

1、定义

抽象部分与实现部分分离,使它们都可以独立的变化。(实现系统可能有多角度分类,每一种分类都可能发生变化,那么就按不同的角度分离出来,让它们独立变化,减少耦合

2、使用场景

  • 1、如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系,通过桥接模式可以使它们在抽象层建立一个关联关系。
  • 2、对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用。
  • 3、一个类存在两个独立变化的维度,且这两个维度都需要进行扩展。

3、优缺点

优点: 1、抽象和实现的分离。 2、优秀的扩展能力。 3、实现细节对客户透明。

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

4、模式结构分析

  • Abstraction(抽象类):用于定义抽象类的接口,它一般是抽象类而不是接口,其中定义了一个Implementor(实现类接口)类型的对象并可以维护该对象,它与Implementor之间具有关联关系,它既可以包含抽象业务方法,也可以包含具体业务方法。
  • RefinedAbstraction(扩充抽象类):扩充由Abstraction定义的接口,通常情况下它不再是抽象类而是具体类,它实现了在Abstraction中声明的抽象业务方法,在RefinedAbstraction中可以调用在Implementor中定义的业务方法。
  • Implementor(实现类接口):定义实现类的接口,这个接口不一定要与Abstraction的接口完全一致,事实上这两个接口可以完全不同,一般而言,Implementor接口仅提供基本操作,而Abstraction定义的接口可能会做更多更复杂的操作。Implementor接口对这些基本操作进行了声明,而具体实现交给其子类。通过关联关系,在Abstraction中不仅拥有自己的方法,还可以调用到Implementor中定义的方法,使用关联关系来替代继承关系。
  • ConcreteImplementor(具体实现类):具体实现Implementor接口,在不同的ConcreteImplementor中提供基本操作的不同实现,在程序运行时,ConcreteImplementor对象将替换其父类对象,提供给抽象类具体的业务操作方​​​​​​法。

桥接模式——合成/聚合复用原则的最佳实践_第1张图片

二、实例实现

1、实例场景分析

我们现在的手机有不同的品牌,手机里面安装了很多的软件,我们发现大多数软件对于手机来说是通用的,一个手机想要使用某个软件,我们只需下载安装即可。手机与软件之间就可以使用“桥接模式”来模拟。

这里使用到的就是“合成/聚合复用原则”,一个手机包含多个软件。UML图如下:

桥接模式——合成/聚合复用原则的最佳实践_第2张图片

2、Abstraction(抽象类)

package com.mfc.design.桥接模式;

import java.util.ArrayList;
import java.util.List;

/**
 * @author MouFangCai
 * @date 2019/10/22 10:48
 *
 * @description 手机品牌类 抽象类
 */
public abstract class Phone_Abstraction {

    // 一个手机 可以安装多个软件
    private List softList = new ArrayList<>();

    // 安装软件
    public  void addSoft(Soft_Implementor soft){
        softList.add(soft);
    }
    // 软件运行
    public abstract void run();

    public List getSoftList() {
        return softList;
    }
}

3、RefinedAbstraction(扩充抽象类)

package com.mfc.design.桥接模式;

/**
 * @author MouFangCai
 * @date 2019/10/22 11:24
 *
 * @description 手机 扩充抽象类
 *  手机品牌1
 */
public class Brand1_RefinedAbstraction extends Phone_Abstraction {

    private String brandName;

    public Brand1_RefinedAbstraction() {
        this.brandName = "华为智能手机";
    }

    @Override
    public void run() {
        System.out.println(brandName + "--正在运行软件:");
        for (Soft_Implementor soft: getSoftList()) {
            soft.run();
        }
    }
}
package com.mfc.design.桥接模式;

/**
 * @author MouFangCai
 * @date 2019/10/22 11:24
 *
 * @description 手机 扩充抽象类
 *  手机品牌2
 */
public class Brand2_RefinedAbstraction extends Phone_Abstraction {

    private String brandName;

    public Brand2_RefinedAbstraction() {
        this.brandName = "诺基亚老年手机";
    }

    @Override
    public void run() {
        System.out.println(brandName + "--正在运行软件:");
        for (Soft_Implementor soft: getSoftList()) {
            soft.run();
        }
    }
}

4、Implementor(实现类接口)

package com.mfc.design.桥接模式;

/**
 * @author MouFangCai
 * @date 2019/10/22 10:50
 *
 * @description 软件类  实现类接口
 */
public interface Soft_Implementor {
    // 软件运行方法
    void run();
}

5、ConcreteImplementor(具体实现类)

package com.mfc.design.桥接模式;

/**
 * @author MouFangCai
 * @date 2019/10/22 11:31
 *
 * @description 具体实现类
 */
public class Game_Soft implements Soft_Implementor {
    @Override
    public void run() {
        System.out.println("手机游戏——运行");
    }
}
package com.mfc.design.桥接模式;

/**
 * @author MouFangCai
 * @date 2019/10/22 11:31
 *
 * @description 具体实现类
 */
public class AddressList_Soft implements Soft_Implementor {
    @Override
    public void run() {
        System.out.println("手机通讯录——运行");
    }
}

6、客户端

package com.mfc.design.桥接模式;

/**
 * @author MouFangCai
 * @date 2019/10/22 11:35
 * @description
 */
public class Client_Bridge {

    public static void main(String[] args) {
        Brand1_RefinedAbstraction phone1 = new Brand1_RefinedAbstraction();
        // 安装软件
        phone1.addSoft(new Game_Soft());
        phone1.addSoft(new AddressList_Soft());
        // 运行软件
        phone1.run();

        System.out.println();
        Brand2_RefinedAbstraction phone2 = new Brand2_RefinedAbstraction();
        phone2.addSoft(new AddressList_Soft());
        phone2.run();
    }
}

7、结果展示

华为智能手机--正在运行软件:
手机游戏——运行
手机通讯录——运行

诺基亚老年手机--正在运行软件:
手机通讯录——运行

Process finished with exit code 0 

可以发现,使用“桥接模式”后,如果有新的“手机品牌”或新的“软件”,只需要新增一个实体类即可,符合“开放封闭”原则。

你可能感兴趣的:(Java设计模式)