我们知道Java里共有23种设计模式,使客户端对单个对象和组合对象保持一致的方式处理,组合模式属于结构型设计模式。
组合模式
定义
组合模式也称为整体-部分模式,它的宗旨是通过将单个对象(叶子节点)和组合对象(树枝节点)用相同的接口进行表示。
适用场景
(1) 希望客户端可以忽略组合对象与单个对象的差异。
(2) 对象层次具备整体和部分,呈树形结构(如树形结构、公司组织架构等)。
优点
(1) 清楚地定义分层次的复杂对象,表示对象的全部或部分层次。
(2) 让客户端忽略了层次的差异,方便对整个层次结构进行控制。
(3) 简化了客户端代码,符合开闭原则。
缺点
(1) 限制类型时会更加负责。
(2) 使设计变得更加抽象。
透明组合模式实例
所有公共方法都定义在 Component 中,这样做的好处是客户端无需分辨是叶子节点(Leaf)和树枝节点(Composite),它们具备完全一致的接口。
public abstract class Component {
public void addChild(Component component) {
throw new UnsupportedOperationException("不支持添加操作");
}
public void removeChild(Component component) {
throw new UnsupportedOperationException("不支持删除操作");
}
public String getName(Component component) {
throw new UnsupportedOperationException("不支持获取名称操作");
}
public double getPrice(Component component) {
throw new UnsupportedOperationException("不支持获取价格操作");
}
public void print() {
throw new UnsupportedOperationException("不支持打印操作");
}
}
public class Course extends Component {
private String name;
private double price;
public Course(String name, double price) {
this.name = name;
this.price = price;
}
@Override
public String getName(Component component) {
return this.name;
}
@Override
public double getPrice(Component component) {
return this.price;
}
@Override
public void print() {
System.out.println(name + " (¥" + price + "元)");
}
}
public class CoursePackage extends Component {
private String name;
private Integer level;
private List<Component> items = new ArrayList<Component>();
public CoursePackage(String name, Integer level) {
this.name = name;
this.level = level;
}
@Override
public void addChild(Component component) {
items.add(component);
}
@Override
public String getName(Component component) {
return this.name;
}
@Override
public void removeChild(Component component) {
items.remove(component);
}
@Override
public void print() {
System.out.println(this.name);
for (Component component : items) {
//控制显示格式
if (this.level != null) {
for (int i = 0; i < this.level; i++) {
//打印空格控制格式
System.out.print(" ");
}
for (int i = 0; i < this.level; i++) {
//每一行开始打印一个+号
if (i == 0) {
System.out.print("+");
}
System.out.print("-");
}
}
//打印标题
component.print();
}
}
}
public class Test {
public static void main(String[] args) {
System.out.println("============透明写法的组合模式===========");
Component javaBase = new Course("Java 入门课程", 8280);
Component ai = new Course("人工智能", 5000);
Component packageCourse = new CoursePackage("Java 架构师课程", 2);
Component design = new Course("Java 设计模式", 1500);
Component source = new Course("并发编程", 2000);
Component softSkill = new Course("源码分析", 3000);
packageCourse.addChild(design);
packageCourse.addChild(source);
packageCourse.addChild(softSkill);
Component catalog = new CoursePackage("课程主目录", 1);
catalog.addChild(javaBase);
catalog.addChild(ai);
catalog.addChild(packageCourse);
catalog.print();
}
}
安全组合模式实例
安全组合模式是只规定系统各个层次的最基础的一致行为,而把组合(树节点)本身的方法(管理子类对象的添加,删除等)放到自身当中。
public abstract class Directory {
protected String name;
public Directory(String name) {
this.name = name;
}
public abstract void show();
}
public class File extends Directory {
public File(String name) {
super(name);
}
@Override
public void show() {
System.out.println(this.name);
}
}
public class Folder extends Directory {
private List<Directory> dirs;
private Integer level;
public Folder(String name, Integer level) {
super(name);
this.level = level;
dirs = new ArrayList<Directory>();
}
public boolean add(Directory dir) {
return this.dirs.add(dir);
}
public boolean remove(Directory dir) {
return this.dirs.remove(dir);
}
public Directory get(int index) {
return this.dirs.get(index);
}
@Override
public void show() {
System.out.println(this.name);
for (Directory dir : this.dirs) {
//控制显示格式
if (this.level != null) {
//打印空格控制格式
for (int i = 0; i < this.level; i++) {
System.out.print(" ");
}
for (int i = 0; i < this.level; i++) {
//每一行开始打印一个+号
if (i == 0) {
System.out.print("+");
}
System.out.print("-");
}
}
//打印名称
dir.show();
}
}
}
public class Test {
public static void main(String[] args) {
System.out.println("============安全写法的组合模式===========");
File qq = new File("QQ.exe");
File wx = new File("微信.exe");
Folder office = new Folder("办公软件", 2);
File word = new File("Word.exe");
File ppt = new File("PowerPoint.exe");
File excel = new File("Excel.exe");
office.add(word);
office.add(ppt);
office.add(excel);
Folder wps = new Folder("金山软件", 3);
wps.add(new File("WPS.exe"));
office.add(wps);
Folder root = new Folder("根目录", 1);
root.add(qq);
root.add(wx);
root.add(office);
root.show();
}
}