前言
设计模式可能是博客圈最热门的话题之一。但是,用来说明每个设计模式的例子通常不是很形象。为了挽救这一点,这篇博客将用一个简单有效的例子来解释组合模式。
我们不会再重复解释这个模型的概念。唯一需要记住的是组合模式通常用在一个树结构的递归操作上。
组合模式例子
假设有一栋建筑,这个建筑有几层楼,每层楼有几个房间。
这个建筑的神奇之处在于,它没有一个总开关。因此,当需要关闭或是开启整栋楼的灯时,就不得不逐层逐个房间按动开关。
为了改变这种情况,我们需要首先定义一个包含开关灯操作的基本接口。这个接口我们命名为Component
,对应于组合模式中的Component
。
public interface Component {
void switchLightsOn();
void switchLightsOff();
}
接着,我们定义表示建筑的类Building,Floor和Room
。每个类实现该接口,并且实现的逻辑如下:
- Building的开关灯操作意味着整栋楼都将开灯或关灯
- Floor的开关灯操作意味着整层楼的开灯或关灯
- Room的开关灯操作意味着该房间的开灯或关灯
以下是三个类的内容:
Building
public class Building extends ArrayList<Floor> implements Component{
@Override
public void switchLightsOn() {
for (Floor floor : this) {
floor.switchLightsOn();
}
}
@Override
public void switchLightsOff() {
for (Floor floor : this) {
floor.switchLightsOff();
}
}
}
Floor
public class Floor extends ArrayList<Room> implements Component {
private int floorNumber;
public Floor(int floorNumber){
this.floorNumber=floorNumber;
}
@Override
public void switchLightsOn() {
for (Room room : this) {
room.switchLightsOn();
}
}
@Override
public void switchLightsOff() {
for (Room room : this) {
room.switchLightsOff();
}
}
}
Room
public class Room implements Component {
private boolean lightsOn = false;
private int roomNumber;
public Room(int roomNumber){
this.roomNumber=roomNumber;
}
@Override
public void switchLightsOn() {
lightsOn = true;
}
@Override
public void switchLightsOff() {
lightsOn = false;
}
public boolean isLightsOn() {
return lightsOn;
}
}
补充说明一下:
- 出于方便,Building类和Floor类直接继承了ArrayList来获得其容器的功能
- Building将关灯的操作传递给其下所有的楼层。类似的,每个楼层将关灯的操作传递给每个房间。这种递归传递时组合模式独有的一个特点。
- 总体的效果是Building上的行为启动了一系列操作并传递给Floors和Rooms。这种多米诺骨牌效应也是组合模式的一个特点。
看一下具体的运行情况。首先,我们需要新建一个Building(默认情况下,灯是关闭状态)。之后,调用建筑的switchLightsOn
方法,打开建筑中的所有房间的灯。
public class CompositeTest {
private Building building;
@Before
public void createBuilding(){
building = new Building();
//1st floor
Floor floor = new Floor(1);
floor.add(new Room(11));
floor.add(new Room(12));
building.add(floor);
//2nd floor
floor = new Floor(2);
floor.add(new Room(21));
floor.add(new Room(22));
floor.add(new Room(23));
building.add(floor);
//3rd floor
floor = new Floor(3);
floor.add(new Room(31));
floor.add(new Room(32));
floor.add(new Room(33));
building.add(floor);
}
@Test
public void buildingLightsAreOn(){
//checking that all rooms are off
for(Floor floor : building){
for(Room room : floor){
assertEquals(false,room.isLightsOn());
}
}
building.switchLightsOn();
//checking that all rooms are on
for(Floor floor : building){
for(Room room : floor){
assertEquals(true,room.isLightsOn());
}
}
}
}
想要了解更多开发技术,面试教程以及互联网公司内推,欢迎关注我的微信公众号!将会不定期的发放福利哦~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。