目录
场景
不用模式实现
代码实现
有何问题
解决方案
代码改造
组合模式优缺点
思考
何时选用
场景
不用模式实现
代码实现
叶子对象
package day14组合模式;
/**
* 叶子对象
*/
public class Leaf {
/**
* 叶子对象的名字
*/
private String name = "";
/**
* 构造方法,传入叶子对象的名字
*/
public Leaf(String name){
this.name = name;
}
/**
* 输出叶子对象的结构
*/
public void printStruct(String preStr){
System.out.println(preStr + "_" + name);
}
}
组合对象
package day14组合模式;
import java.util.ArrayList;
import java.util.Collection;
/**
* 组合对象,组合对象里面包含其他的组合对象或者是叶子对象
* 由于类型不同,需要分开记录
*/
public class Composite {
/**
* 用来记录包含的其他组合对象
*/
private Collection<Composite> childComposite = new ArrayList<>();
/**
* 用来记录包含的其他叶子对象
*/
private Collection<Leaf> childLeaf = new ArrayList<>();
/**
* 组合对象的名字
*/
private String name = "";
/**
* 构造方法
*/
public Composite(String name){
this.name = name;
}
/**
* 向组合对象加入被它包含的其他组合对象
* @param c 被它包含的其他组合对象
*/
public void addComposite(Composite c){
this.childComposite.add(c);
}
/**
* 向组合对象加入被它包含的叶子对象
* @param leaf 被它包含的叶子对象
*/
public void addLeaf(Leaf leaf){
this.childLeaf.add(leaf);
}
/**
* 输出组合对象自身的结构
*/
public void printStruct(String prestr){
// 先把自己输出去
System.out.println(prestr + "+" + this.name);
// 然后添加一个空格,表示向后缩进一个空格,输出自己包含的叶子对象
prestr += " ";
for (Leaf leaf : childLeaf) {
leaf.printStruct(prestr);
}
// 输出当前对象的子对象了
for (Composite c : childComposite) {
// 递归输出每个子对象
c.printStruct(prestr);
}
}
}
Client
package day14组合模式;
public class Client {
public static void main(String[] args) {
// 定义所有的组合对象
Composite root = new Composite("服装");
Composite c1 = new Composite("男装");
Composite c2 = new Composite("女装");
// 定义所有的叶子对象
Leaf leaf1 = new Leaf("衬衣");
Leaf leaf2 = new Leaf("夹克");
Leaf leaf3 = new Leaf("裙子");
Leaf leaf4 = new Leaf("套装");
// 按照树的结构来组合 组合对象和叶子对象
root.addComposite(c1);
root.addComposite(c2);
c1.addLeaf(leaf1);
c1.addLeaf(leaf2);
c2.addLeaf(leaf3);
c2.addLeaf(leaf4);
// 调用跟对象的输出功能来输出整棵树
root.printStruct("");
}
}
有何问题
必须区分组合对象和叶子对象,并进行有区别的对待
解决方案
组合模式
定义:
思路:将组合对象和叶子对象统一起来。通过引入一个抽象的组件对象,作为组合对象和叶子对象的父对象,这样就统一起来了。
代码改造
抽象父组件对象
package day14组合模式.Component;
/**
* 抽象的父组件对象
*/
public abstract class Component {
/**
* 输出组件自身的名称
*/
public abstract void printStruct(String preStr);
/**
* 向组合对象中加入组件对象
* @param child
*/
public void addChild(Component child){
throw new UnsupportedOperationException("对象不支持这个功能");
}
/**
* 从组合对象中移出某个组件对象
* @param child
*/
public void removeChild(Component child){
throw new UnsupportedOperationException("对象不支持这个功能");
}
/**
* 返回某个索引对应的组件对象
* @param index 需要获取的组件对象的索引,索引从0开始
* @return 索引对应的组件对象
*/
public Component getChildren(int index){
throw new UnsupportedOperationException("对象不支持这个功能");
}
}
Leaf类
继承一下这个抽象类,别的没有变化
package day14组合模式;
import day14组合模式.Component.Component;
/**
* 叶子对象
*/
public class Leaf extends Component {
/**
* 叶子对象的名字
*/
private String name = "";
/**
* 构造方法,传入叶子对象的名字
*/
public Leaf(String name){
this.name = name;
}
/**
* 输出叶子对象的结构
*/
public void printStruct(String preStr){
System.out.println(preStr + name);
}
}
组合对象类
package day14组合模式;
import day14组合模式.Component.Component;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* 组合对象,组合对象里面包含其他的组合对象或者是叶子对象
* 由于类型不同,需要分开记录
*/
public class Composite extends Component {
/**
* 用来存储组合对象中包含的子组件对象
*/
private List<Component> childComponents = null;
/**
* 组合对象的名字
*/
private String name = "";
/**
* 构造方法
*/
public Composite(String name) {
this.name = name;
}
public void addChild(Component child) {
// 延迟初始化
if (childComponents == null) {
childComponents = new ArrayList<>();
}
childComponents.add(child);
}
/**
* 输出组合对象自身的结构
*/
public void printStruct(String prestr) {
// 先把自己输出去
System.out.println(prestr + this.name);
// 如果还包含有子组件,那么就输出这些子组件对象
if (this.childComponents != null) {
prestr += " ";
// 输出当前对象的子对象了
for (Component c : childComponents) {
// 递归输出每个子对象
c.printStruct(prestr);
}
}
}
}
去掉了之前区分组合对象和叶子对象的方法。
Client
// 定义所有的组合对象
Component root = new Composite("服装");
Component c1 = new Composite("男装");
Component c2 = new Composite("女装");
// 定义所有的叶子对象
Component leaf1 = new Leaf("衬衣");
Component leaf2 = new Leaf("夹克");
Component leaf3 = new Leaf("裙子");
Component leaf4 = new Leaf("套装");
// 按照树的结构来组合 组合对象和叶子对象
root.addChild(c1);
root.addChild(c2);
c1.addChild(leaf1);
c1.addChild(leaf2);
c2.addChild(leaf3);
c2.addChild(leaf4);
// 调用跟对象的输出功能来输出整棵树
root.printStruct("");
组合模式优缺点
思考
本质:统一叶子对象和组合对象,一视同仁全部当成Component对象
何时选用