組合模式 屬於結構型模式。它將對象組合成樹形結構以表示「部分-整體」的層次關係,使得客戶端對單個對象(葉子)和組合對象(容器)的使用具有一致性。
add/remove/getChild)。// 1. 抽象構件
public abstract class Equipment {
protected String name;
public Equipment(String name) { this.name = name; }
public abstract double netPrice();
public abstract double discountPrice();
// 容器管理方法,默認拋異常或返回 false
public boolean add(Equipment e) { throw new UnsupportedOperationException(); }
public boolean remove(Equipment e) { throw new UnsupportedOperationException(); }
public Iterator iterator() { return Collections.emptyIterator(); }
}
// 2. 葉子:磁盤
public class Disk extends Equipment {
public Disk(String name) { super(name); }
@Override public double netPrice() { return 100; }
@Override public double discountPrice() { return 50; }
}
// 3. 容器抽象類
public abstract class CompositeEquipment extends Equipment {
private List children = new ArrayList<>();
public CompositeEquipment(String name) { super(name); }
@Override public boolean add(Equipment e) { return children.add(e); }
@Override public boolean remove(Equipment e) { return children.remove(e); }
@Override public Iterator iterator() { return children.iterator(); }
// 業務邏輯遞歸委派
@Override public double netPrice() {
return children.stream().mapToDouble(Equipment::netPrice).sum();
}
@Override public double discountPrice() {
return children.stream().mapToDouble(Equipment::discountPrice).sum();
}
}
// 4. 具體容器:機箱、機櫃
public class Chassis extends CompositeEquipment {
public Chassis(String name) { super(name); }
@Override public double netPrice() { return 200 + super.netPrice(); } // 自身價格 + 子設備
@Override public double discountPrice() { return 100 + super.discountPrice(); }
}
public class Cabinet extends CompositeEquipment {
public Cabinet(String name) { super(name); }
@Override public double netPrice() { return 500 + super.netPrice(); }
@Override public double discountPrice() { return 250 + super.discountPrice(); }
}
// 5. 客戶端
public class Client {
public static void main(String[] args) {
Cabinet cabinet = new Cabinet("機櫃");
Chassis chassis = new Chassis("機箱");
cabinet.add(chassis);
chassis.add(new Disk("硬盤 1TB"));
chassis.add(new Disk("SSD 512GB"));
System.out.println("淨價: " + cabinet.netPrice()); // 統一調用
System.out.println("折扣價: " + cabinet.discountPrice());
}
}
Component 接口。ForumThread 包含多個 ForumMessage(回帖樹)即採用組合模式。在 Component 接口中聲明 add/remove 方法雖便於多態,但會導致 Leaf 類實現無意義的方法(拋異常)。替代方案:僅在 Composite 類中聲明管理方法,客戶端針對容器類型調用(犧牲部分透明性換取安全性)。