首先看一道题:在水果盘中有一些水果,大水果盘中不仅可以放水果而且可以放小一点的水果盘,水果有吃的方法,请模拟该场景吃水果。
**分析:**我们可以不管是大水果盘还是小水果盘,还是水果,都给它看做一个组件,该组件可以定义为抽象类,并且定义基本的抽象的吃方法,添加组件(组件可以是水果也可以是盘子)的方法,然后让水果类和盘子类分别继承组件类,并根据需要重写一些方法。
package zuhemoshi;
public abstract class Component {
public abstract void eat();
public abstract void add(Component c);
}
package zuhemoshi;
public class Fruit extends Component {
public void eat() {
System.out.println("吃水果");
}
/*Component是抽象类,普通类继承它必须实现所有的方法,
* 但add方法对于水果来说是不必要的,所以通过抛出异常
* 来解决。(这是透明形式的组合模式)
*/
public void add(Component c) {
throw new IllegalException();
}
}
package zuhemoshi;
public class IllegalException extends RuntimeException {
IllegalException(){
System.out.println("水果只能吃");
}
}
package zuhemoshi;
import java.util.ArrayList;
public class Plate extends Component {
public ArrayList<Component> list = new ArrayList<Component>();
@Override
public void eat() {
if(list==null){
System.out.println("遇到一个没有水果的空盘子");
}
for(Component c:list){
c.eat();
}
}
@Override
public void add(Component c) {
list.add(c);
}
}
package zuhemoshi;
/**
* @author hpc
* @Date:2018-10-14下午3:56:46
* 功能:组合模式测试类
*/
public class Client {
public static void main(String[] args) {
Component plate1 = new Plate();
Component plate2 = new Plate();
Component plate3 = new Plate();
Component plate4 = new Plate();
Component fruit1 = new Fruit();
Component fruit2 = new Fruit();
Component fruit3 = new Fruit();
Component fruit4 = new Fruit();
plate1.add(plate2);
plate1.add(fruit1);
plate1.add(fruit2);
plate2.add(fruit3);
plate2.add(plate3);
plate3.add(plate4);
plate4.add(fruit4);
plate1.eat();
}
}
组合模式的关键是定义了一个抽象构件类,它既可以
代表叶子,又可以代表容器,而客户端针对该抽象构
件类进行编程,无须知道它到底表示的是叶子还是容
器,可以对其进行统一处理。
上述是透明形式的组合模式,在Fruit类的注释中已经说过,Fruit类并不需要add方法,但是由于普通类继承抽象类的原因有必须要重写,所以另外一个安全模式,在抽象父类中不写add方法,在plate类中新写一个add方法,但是这样就在测试类中就不能由父类声明了,要写出具体子类。