组合设计模式

一、组合模式

1、定义

组合模式(Composite Pattern)又称作整体-部分(Part-Whole)模式,其宗旨是通过将单个对象(叶子节点)和组织对象(树枝节点)用相同的接口进行表示,使得客户对单个对象和组合对象的使用具有一致性,属于结构型设计模式。

2、结构

(1)模式的结构

主要角色如下:

  • 抽象组成角色(Component):单个对象和组织对象的抽象基类或者接口,表示整个树形结构中的对象都属于同一种类型,用于访问和管理子节点。
  • 组织对象角色(Composite):树枝节点,用来存储子节点,并实现了组织接口中的操作方法。
  • 单个对象角色(Left):叶子节点,它没有子节点,它不需要实现组织接口中的操作方法。

(2)组合模式有两种

  • 透明组合模式: 组织接口中声明用来管理子对象的所有行为方法,好处就是树枝节点和叶子节点对外界没有区别,它们具备完全一致的行为接口,缺点时,叶子节点本身不具备组织接口的行为方法,所以实现它们是没有意义的。
  • 安全组合模式: 组织接口中不声明用来管理子对象的所有行为方法,所以叶子节点也就不需要去实现它们。而是在组织节点中声明用来管理子对象的所有行为方法。这样做由于不够透明,树枝节点和叶子节点将不具有相同的接口,客户端的调用需要做相应的判断,带来了不便。

3、优缺点

优点:

  • 清楚地定义各层次的复杂对象,表示对象的全部或部分层次。
  • 让客户端忽略了层次的差异,方便对整个层次结构进行控制。
  • 符合开闭原则。

缺点:

  • 限制类型时会较为复杂。
  • 使设计变得更加抽象。

4、使用场景

  • 希望客户端可以忽略组个对象与单个对象的差异。
  • 对象层次具备整体和部分,呈树形结构。

5、在框架源码中使用

  • Java中 HashMap 的 putAll方法,存储使用了一个静态内部类的数据Node[]。
  • Mybatis源码中解析Mapping文件中的 SQL语句时,使用到的 SqlNode类的作用非常关键。

二、模式的通用实现

1、透明组合模式

代码如下:

public class CompositePattern1 {
	public static void main(String[] args) {

		Component1 root = new Composite1("root");

		Component1 branch1 = new Composite1("branch1");
		Component1 branch2 = new Composite1("branch2");

		Component1 leaf1 = new Leaf1("leaf1");
		Component1 leaf2 = new Leaf1("leaf2");
		Component1 leaf3 = new Leaf1("leaf3");
		Component1 leaf4 = new Leaf1("leaf4");

		root.addChild(branch1);
		root.addChild(leaf3);
		branch1.addChild(leaf1);
		branch1.addChild(branch2);
		branch2.addChild(leaf2);
		branch2.addChild(leaf4);

		String display = root.display();
		System.out.println(display);
		System.out.println("===============");
		System.out.println("branch2.getChild(1).display() -> " + branch2.getChild(1).display());
		branch2.removeChild(leaf4);
		String display2 = root.display();
		System.out.println(display2);
	}
}

// 抽象组成角色
abstract class Component1 {

	protected String name;

	public Component1(String name) {
		this.name = name;
	}

	public abstract String display();

	public boolean addChild(Component1 component1) {
		throw new RuntimeException(" addChild 不支持");
	}

	public boolean removeChild(Component1 component1) {
		throw new RuntimeException(" removeChild 不支持");
	}

	public Component1 getChild(int index) {
		throw new RuntimeException(" getChild 不支持");
	}

}

// 组织对象角色
class Composite1 extends Component1 {

	private List<Component1> component1List;

	public Composite1(String name) {
		super(name);
		this.component1List = new ArrayList<Component1>();
	}

	@Override
	public String display() {
		StringBuilder sb = new StringBuilder(this.name);

		for (int i = 0; i < component1List.size(); i++) {
			Component1 component1 = component1List.get(i);
			sb.append("\n");
			sb.append(component1.display());
		}
		return sb.toString();
	}

	@Override
	public boolean addChild(Component1 component1) {
		return component1List.add(component1);
	}

	@Override
	public boolean removeChild(Component1 component1) {
		return component1List.remove(component1);
	}

	@Override
	public Component1 getChild(int index) {
		return component1List.get(index);
	}
}

// 单个对象角色
class Leaf1 extends Component1 {

	public Leaf1(String name) {
		super(name);
	}

	@Override
	public String display() {
		return this.name;
	}
}

在这里插入图片描述

2、安全组合模式

代码如下:

public class CompositePattern2 {
	public static void main(String[] args) {

		Composite2 root = new Composite2("root");

		Composite2 branch1 = new Composite2("branch1");
		Composite2 branch2 = new Composite2("branch2");

		Component2 leaf1 = new Leaf2("leaf1");
		Component2 leaf2 = new Leaf2("leaf2");
		Component2 leaf3 = new Leaf2("leaf3");
		Component2 leaf4 = new Leaf2("leaf4");

		root.addChild(branch1);
		root.addChild(leaf3);
		branch1.addChild(leaf1);
		branch1.addChild(branch2);
		branch2.addChild(leaf2);
		branch2.addChild(leaf4);

		String display = root.display();
		System.out.println(display);
		System.out.println("===============");
		System.out.println("branch2.getChild(1).display() -> " + branch2.getChild(1).display());
		branch2.removeChild(leaf4);
		String display2 = root.display();
		System.out.println(display2);
	}
}

// 抽象组成角色
abstract class Component2 {

	protected String name;

	public Component2(String name) {
		this.name = name;
	}

	public abstract String display();

}

// 组织对象角色
class Composite2 extends Component2 {

	private List<Component2> component2List;

	public Composite2(String name) {
		super(name);
		this.component2List = new ArrayList<Component2>();
	}

	@Override
	public String display() {
		StringBuilder sb = new StringBuilder(this.name);
		for (int i = 0; i < component2List.size(); i++) {
			sb.append("\n");
			Component2 component2 = component2List.get(i);
			sb.append(component2.display());
		}
		return sb.toString();
	}

	public boolean addChild(Component2 component2) {
		return component2List.add(component2);
	}

	public boolean removeChild(Component2 component2) {
		return component2List.remove(component2);
	}

	public Component2 getChild(int index) {
		return component2List.get(index);
	}
}

// 单个对象角色
class Leaf2 extends Component2 {

	public Leaf2(String name) {
		super(name);
	}

	@Override
	public String display() {
		return this.name;
	}
}

三、模式的应用实例

以文件系统为例,目录包含文件夹和文件。下面使用安全组合模式实现。

(1)目录:抽象组成角色

public abstract class Directory {

	protected String name;

	public Directory(String name) {
		this.name = name;
	}

	public abstract void show();
}

(2)文件夹:组织对象角色

public class Folder extends Directory {
	private List<Directory> dirList;

	private Integer depth;

	public Folder(String name, Integer depth) {
		super(name);
		this.depth = depth;
		dirList = new ArrayList<>();
	}

	public void list() {
		for (Directory dir : this.dirList) {
			System.out.println(dir.name);
		}
	}

	@Override
	public void show() {
		System.out.println(this.name);
		for (Directory dir : this.dirList) {
			if (this.depth != null) {
				for (Integer integer = 0; integer < this.depth; integer++) {
					System.out.print(" ");
				}
				for (Integer integer = 0; integer < this.depth; integer++) {
					if (integer == 0) {
						System.out.print("+");
					}
					System.out.print("-");
				}
			}
			dir.show();
		}
	}

	public boolean addChild(Directory directory) {
		return dirList.add(directory);
	}

	public boolean removeChild(Directory directory) {
		return dirList.remove(directory);
	}

	public Directory getChild(int index) {
		return dirList.get(index);
	}
}

(3)文件:单个对象角色

public class File extends Directory{

    public File(String name) {
        super(name);
    }

    @Override
    public void show() {
        System.out.println(this.name);
    }
}

(4)测试

	public static void main(String[] args) {
		Folder root = new Folder("root", 1);
		File dy = new File("抖音.exe");
		File qq = new File("QQ.exe");
		root.addChild(dy);
		root.addChild(qq);

		Folder office = new Folder("办公软件", 2);
		File word = new File("Word.exe");
		File ppt = new File("PPT.exe");
		File excel = new File("Excel.exe");
		office.addChild(word);
		office.addChild(ppt);
		office.addChild(excel);

		Folder devTools = new Folder("开发工具", 3);
		File idea = new File("idea.exe");
		File navicat = new File("navicat.exe");
		devTools.addChild(idea);
		devTools.addChild(navicat);

		office.addChild(devTools);
		root.addChild(office);

		System.out.println("========show方法======");
		root.show();
		System.out.println("========list方法======");
		root.list();
	}

在这里插入图片描述

– 求知若饥,虚心若愚。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值