瞎说设计模式第七回:组合模式

Posted 竹森技术分享

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了瞎说设计模式第七回:组合模式相关的知识,希望对你有一定的参考价值。

上一篇,通过车辆定制来说了说桥接模式,今天我们来聊聊组合模式。思来想去,就用车子启动前的自检来说吧。


大多数车子通电之后,会进行一遍自检,把全车各个部分组件迅速地检查一遍。一些组件是一级组件,一些是一级组件下的二级组件等。


总的来说,自检的范围包括机械部分、电器部分和油液部分等。


我们来设计这样一个自检系统。


首先,建立一个所有组件的抽象类,定义一些抽象的基本行为:

public abstract class AbstractCompont { public abstract void add(AbstractCompont compont); public abstract void remove(AbstractCompont compont); public abstract AbstractCompont getChild(int i); public abstract void checkHealth();}

接下来,分别实现机械、电器和油液三个部分的组件类。


机械组件类:

public class MechanicalCompont extends AbstractCompont { private String name;
public MechanicalCompont(String name) { this.name = name; }
@Override public void add(AbstractCompont compont) { System.out.println("不支持该方法"); }
@Override public void remove(AbstractCompont compont) { System.out.println("不支持该方法"); }
@Override public AbstractCompont getChild(int i) { System.out.println("不支持该方法"); return null; }
@Override public void checkHealth() { //模拟组件健康检查 System.out.println("启动自检,对机械部分——" + name + "进行健康检查"); }}

电器组件类:

public class ElectricalCompont extends AbstractCompont { private String name;
public ElectricalCompont(String name) { this.name = name; }
@Override public void add(AbstractCompont compont) { System.out.println("不支持该方法"); }
@Override public void remove(AbstractCompont compont) { System.out.println("不支持该方法"); }
@Override public AbstractCompont getChild(int i) { System.out.println("不支持该方法"); return null; }
@Override public void checkHealth() { //模拟组件健康检查 System.out.println("启动自检,对电器部分——" + name + "进行健康检查"); }}

油液组件类:

public class OilAndLiquidCompont extends AbstractCompont { private String name;
public OilAndLiquidCompont(String name) { this.name = name; }
@Override public void add(AbstractCompont compont) { System.out.println("不支持该方法"); }
@Override public void remove(AbstractCompont compont) { System.out.println("不支持该方法"); }
@Override public AbstractCompont getChild(int i) { System.out.println("不支持该方法"); return null; }
@Override public void checkHealth() { //模拟组件健康检查 System.out.println("启动自检,对油液部分——" + name + "进行健康检查"); }}

然后,实现一个上层组件类,也就是开头说的一级组件:

public class SuperCompont extends AbstractCompont { private String name; private ArrayList<AbstractCompont> componts = new ArrayList<>();
public SuperCompont(String name) { this.name = name; }
@Override public void add(AbstractCompont compont) { componts.add(compont); }
@Override public void remove(AbstractCompont compont) { componts.remove(compont); }
@Override public AbstractCompont getChild(int i) { return componts.get(i); }
@Override public void checkHealth() { System.out.println("启动自检,对" + name + "进行健康检查");
for (AbstractCompont compont : componts ) { compont.checkHealth(); } }}

最后,定义一个自检控制类,实现自检的组合:

public class CheckController { public static void main(String args[]) { AbstractCompont superCar = new SuperCompont("全车"); AbstractCompont superMechanical = new SuperCompont("机械部分"); AbstractCompont superElectrical = new SuperCompont("电器部分"); AbstractCompont superOilAndLiquid = new SuperCompont("油液部分");
AbstractCompont engine = new MechanicalCompont("发动机系统"); AbstractCompont gearbox = new MechanicalCompont("变速箱系统"); AbstractCompont chassis = new MechanicalCompont("底盘系统"); superMechanical.add(engine); superMechanical.add(gearbox); superMechanical.add(chassis);
AbstractCompont powerSupply = new ElectricalCompont("电源系统"); AbstractCompont startUp = new ElectricalCompont("启动系统"); AbstractCompont ignition = new ElectricalCompont("点火系统"); AbstractCompont light = new ElectricalCompont("照明系统"); AbstractCompont signal = new ElectricalCompont("信号系统"); AbstractCompont meter = new ElectricalCompont("仪表系统"); AbstractCompont ecu = new ElectricalCompont("电控系统"); superElectrical.add(powerSupply); superElectrical.add(startUp); superElectrical.add(ignition); superElectrical.add(light); superElectrical.add(signal); superElectrical.add(meter); superElectrical.add(ecu);
AbstractCompont fuelOil = new OilAndLiquidCompont("燃油情况"); AbstractCompont lubricatingOil = new OilAndLiquidCompont("机油情况"); AbstractCompont transmissionOil = new OilAndLiquidCompont("变速箱油情况"); AbstractCompont coolant = new OilAndLiquidCompont("冷却液情况"); AbstractCompont washerFluid = new OilAndLiquidCompont("玻璃水情况"); superOilAndLiquid.add(fuelOil); superOilAndLiquid.add(lubricatingOil); superOilAndLiquid.add(transmissionOil); superOilAndLiquid.add(coolant); superOilAndLiquid.add(washerFluid);
superCar.add(superMechanical); superCar.add(superElectrical); superCar.add(superOilAndLiquid); superCar.checkHealth();
}}

运行结果如下:

启动自检,对全车进行健康检查启动自检,对机械部分进行健康检查启动自检,对机械部分——发动机系统进行健康检查启动自检,对机械部分——变速箱系统进行健康检查启动自检,对机械部分——底盘系统进行健康检查启动自检,对电器部分进行健康检查启动自检,对电器部分——电源系统进行健康检查启动自检,对电器部分——启动系统进行健康检查启动自检,对电器部分——点火系统进行健康检查启动自检,对电器部分——照明系统进行健康检查启动自检,对电器部分——信号系统进行健康检查启动自检,对电器部分——仪表系统进行健康检查启动自检,对电器部分——电控系统进行健康检查启动自检,对油液部分进行健康检查启动自检,对油液部分——燃油情况进行健康检查启动自检,对油液部分——机油情况进行健康检查启动自检,对油液部分——变速箱油情况进行健康检查启动自检,对油液部分——冷却液情况进行健康检查启动自检,对油液部分——玻璃水情况进行健康检查

我们回顾一下组合模式的定义:将对象组合成树形结构以表示“部分整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。(摘自GoF的《设计模式》)


在车辆自检的例子中,通过AbstractCompont抽象类的各种继承,实现了“单个对象和组合对象的使用具有一致性”,而从全车—部分—系统实现了对对象组合成了树形结构来表示了“部分—整体”的层次结构。在自检控制类CheckController中,可以控制对全局的自检和部分自检,同时,如果有新的自检项目加入时,只需要继承AbstractCompont抽象类,并在CheckController进行灵活组合即可,符合开闭原则。


以上是关于瞎说设计模式第七回:组合模式的主要内容,如果未能解决你的问题,请参考以下文章

Docker第七回(私有Registry)

瞎说设计模式第五回:适配器模式

第七讲:建造者模式

第七课-第二讲 07_02_bash脚本编程之六 使用脚本选项及组合条件测试

第七课-第二讲 07_02_bash脚本编程之六 使用脚本选项及组合条件测试

Linux 0.11 - 进入内核前的苦力活完结篇