设计模式学习笔记——组合模式

组合模式

组合模式,将对象组合合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

代码实现

接口声明Component

/**
 * 接口声明
 * @author xukai 2016年3月26日 下午4:58:37
 *
 */
public abstract class Component {

	protected String name;

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

	public abstract void add(Component component);

	public abstract void remove(Component component);

	public abstract void display(int depth);

}

枝节点Composite

/**
 * 枝节点
 *
 * @author xukai 2016年3月26日 下午5:04:52
 *
 */
public class Composite extends Component {

	private List<Component> children = new ArrayList<Component>();

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

	@Override
	public void add(Component component) {
		children.add(component);
	}

	@Override
	public void remove(Component component) {
		children.remove(component);
	}

	@Override
	public void display(int depth) {
		System.out.println("名称:" + name + ",深度:" + depth);
		for (Component component : children) {
			component.display(depth + 2);
		}
	}

}

叶子节点Leaf

/**
 * 叶节点:无子节点
 * @author xukai 2016年3月26日 下午5:01:45
 *
 */
public class Leaf extends Component {

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

	@Override
	public void add(Component component) {
		System.out.println("添加一个叶子节点");
	}

	@Override
	public void remove(Component component) {
		System.out.println("去除一个叶子节点");
	}

	@Override
	public void display(int depth) {
		System.out.println("名称:" + name + ",深度:" + depth);
	}

}

客户端测试:

public class Client {

	public static void main(String[] args) {
		// 根节点
		Composite root = new Composite("root");

		root.add(new Leaf("叶子节点1"));
		root.add(new Leaf("叶子节点2"));

		Composite comp_A = new Composite("子节点A");
		comp_A.add(new Leaf("A子叶子节点1"));
		comp_A.add(new Leaf("A子叶子节点2"));

		// 根节点添加A子节点
		root.add(comp_A);

		Composite comp_A_B = new Composite("子节点A_B");
		comp_A_B.add(new Leaf("A_B子叶子节点1"));
		comp_A_B.add(new Leaf("A_B子叶子节点2"));

		comp_A.add(comp_A_B);

		// 根节点右生出子节点
		Leaf leaf = new Leaf("叶子节点3");
		root.add(leaf);
		root.display(1);
		System.out.println("====================");
		// 缺营养,挂了
		root.remove(leaf);
		root.display(1);
	}

}

控制台输出:

名称:root,深度:1
名称:叶子节点1,深度:3
名称:叶子节点2,深度:3
名称:子节点A,深度:3
名称:A子叶子节点1,深度:5
名称:A子叶子节点2,深度:5
名称:子节点A_B,深度:5
名称:A_B子叶子节点1,深度:7
名称:A_B子叶子节点2,深度:7
名称:叶子节点3,深度:3
====================
名称:root,深度:1
名称:叶子节点1,深度:3
名称:叶子节点2,深度:3
名称:子节点A,深度:3
名称:A子叶子节点1,深度:5
名称:A子叶子节点2,深度:5
名称:子节点A_B,深度:5
名称:A_B子叶子节点1,深度:7
名称:A_B子叶子节点2,深度:7

测试的结构图:

这里需要注意一下,给Leaf叶子节点也添加了Add和remove方法,这种方式叫做透明方式,即在Component中声明所有用来管理子对象的方法,Component接口的所有子类都具有了Add和Remove。好处是叶节点和枝节点对于外界没有区别,具备完全一致的行为接口。(虽然实现它是没有意义的)

demo

问题:公司管理系统实现。

代码实现

公司的抽象接口Company

/**
 * 公司抽象接口
 *
 * @author xukai 2016年3月26日 下午9:01:47
 *
 */
public abstract class Company {

	protected String name;

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

	public abstract void add(Company company);

	public abstract void remove(Company company);

	public abstract void display(int depth);

	public abstract void lineOfDuty();

}

具体公司类ConcreteCompany

/**
 * 具体公司
 * @author xukai 2016年3月26日 下午9:03:41
 *
 */
public class ConcreteCompany extends Company {

	private List<Company> children = new ArrayList<>();

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

	@Override
	public void add(Company company) {
		children.add(company);
	}

	@Override
	public void remove(Company company) {
		children.remove(company);
	}

	@Override
	public void display(int depth) {
		System.out.println("公司名称:" + name + ",深度" + depth);
		for(Company company : children){
			company.display(depth+2);
		}
	}

	@Override
	public void lineOfDuty() {
		for(Company company : children){
			company.lineOfDuty();
		}
	}

}

具体部门类,人力资源部HRDepartment

/**
 * 人力资源部
 *
 * @author xukai 2016年3月26日 下午9:17:01
 *
 */
public class HRDepartment extends Company {

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

	@Override
	public void add(Company company) {

	}

	@Override
	public void remove(Company company) {

	}

	@Override
	public void display(int depth) {
		System.out.println("部门名称:" + name + ",深度" + depth);
	}

	@Override
	public void lineOfDuty() {
		System.out.println(name + "工作:员工招聘培训管理");
	}

}

财务部,FinanceDepartment

/**
 * 财务部
 *
 * @author xukai 2016年3月26日 下午9:08:07
 *
 */
public class FinanceDepartment extends Company {

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

	@Override
	public void add(Company company) {

	}

	@Override
	public void remove(Company company) {

	}

	@Override
	public void display(int depth) {
		System.out.println("部门名称:" + name + ",深度" + depth);
	}

	@Override
	public void lineOfDuty() {
		System.out.println(name + "的工作:公司财务管理");
	}

}

客户端:

public class Client {

	public static void main(String[] args) {

		ConcreteCompany company = new ConcreteCompany("总公司");
		company.add(new HRDepartment("总公司人力资源部"));
		company.add(new FinanceDepartment("总公司财务部"));

		ConcreteCompany childrenCompany1 = new ConcreteCompany("分公司1");
		childrenCompany1.add(new HRDepartment("分公司1_人力资源部"));
		childrenCompany1.add(new FinanceDepartment("分公司1_财务部"));

		// 总公司添加分公司1
		company.add(childrenCompany1);

		ConcreteCompany childrenCompany2 = new ConcreteCompany("分公司2");
		childrenCompany2.add(new HRDepartment("分公司2_人力资源部"));
		childrenCompany2.add(new FinanceDepartment("分公司2_财务部"));

		// 总公司添加分公司2
		company.add(childrenCompany2);

		ConcreteCompany childrenCompany3 = new ConcreteCompany("分公司3");
		childrenCompany3.add(new HRDepartment("分公司3_人力资源部"));
		childrenCompany3.add(new FinanceDepartment("分公司3_财务部"));

		// 总公司添加分公司3
		company.add(childrenCompany3);
		// 查看公司结构
		company.display(1);
		// 公司部门职责
		company.lineOfDuty();

	}

}

客户端输出:

</pre><pre name="code" class="java">公司名称:总公司,深度1
部门名称:总公司人力资源部,深度3
部门名称:总公司财务部,深度3
公司名称:分公司1,深度3
部门名称:分公司1_人力资源部,深度5
部门名称:分公司1_财务部,深度5
公司名称:分公司2,深度3
部门名称:分公司2_人力资源部,深度5
部门名称:分公司2_财务部,深度5
公司名称:分公司3,深度3
部门名称:分公司3_人力资源部,深度5
部门名称:分公司3_财务部,深度5
总公司人力资源部工作:员工招聘培训管理
总公司财务部的工作:公司财务管理
分公司1_人力资源部工作:员工招聘培训管理
分公司1_财务部的工作:公司财务管理
分公司2_人力资源部工作:员工招聘培训管理
分公司2_财务部的工作:公司财务管理
分公司3_人力资源部工作:员工招聘培训管理
分公司3_财务部的工作:公司财务管理

可以看出,总公司下有三个分公司,分公司和总公司下的部门是一个级别,分公司同样拥有和总公司类似的部门。

总结

当需求中体现部分与整体层次结构是,并且需要忽略组合对象和单个对象的不同,统一地使用组合结构中的所有对象时,可以考虑使用组合模式。

组合模式定义了基本对象和组合对象层次结构。基本对象可以被组合成更复杂的组合对象,而这个组合对象可以又被组合,递归传递。使用时,任何使用基本对象的地方都可以使用组合对象。

组合模式让客户可以一致地使用组合结构和单个对象。

ps:数据结构中的树也是此思想。

时间: 2024-10-05 04:19:26

设计模式学习笔记——组合模式的相关文章

设计模式学习笔记--组合模式

1 using System; 2 3 namespace Composite 4 { 5 /// <summary> 6 /// 作者:bzyzhang 7 /// 时间:2016/5/30 7:11:10 8 /// 博客地址:http://www.cnblogs.com/bzyzhang/ 9 /// Component说明:本代码版权归bzyzhang所有,使用时必须带上bzyzhang博客地址 10 /// </summary> 11 public abstract cl

设计模式学习笔记--外观模式

好久没写设计模式的blog了,这次重新回来填坑,先找一个最简单但是却最常用的设计模式来学习,外观模式.其实说是一个设计模式,其实我们在实际的编程中无时无刻不在用外观模式,可以说这个设计模式已经渗透到编程的各个方便,可能我们自己没感觉出来罢了. 一.外观模式的定义 先来看一下外观模式的定义: 外观模式(Facade),为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层的接口,这个接口使得这一系列子系统更加容易使用. 简单解释一下,所谓外观模式,就是在我们设计系统的时候,将若干个子系统的功

设计模式学习心得&lt;组合模式 Composite&gt;

组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象.组合模式依据树形结构来组合对象,用来表示部分以及整体层次.这种类型的设计模式属于结构型模式,它创建了对象组的树形结构. 这种模式创建了一个包含自己对象组的类.该类提供了修改相同对象组的方式. 概述 意图 将对象组合成树形结构以表示"部分-整体"的层次结构.组合模式使得用户对单个对象和组合对象的使用具有一致性. 主要解决 它在我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客

设计模式学习笔记-工厂模式

一.概述 定义一个用于创建对象的接口,让子类决定实例化哪一个类.工厂方法(Factory Method)使一个类的实例化延迟到其子类: 2.模式中的角色 Product(Map):定义工厂方法所创建的对象的接口. ConcreteProduct(BaiduMap.GaodeMap):具体Product,实现Product接口. Creator(IMapFactory):声明工厂方法,该方法返回一个Product类型的对象. ConcreteCreator(BaiduMapFactory.Gaod

设计模式学习笔记-桥接模式

一.概述 将抽象部分与它的实现部分分离,使它们都可以独立地变化. 二.模式中的角色 Abstraction:定义抽象类的接口:维护一个指向Implementor类型对象的指针: RefinedAbstraction:扩充由Abstraction定义的接口: Implementor:定义具体行为,具体特征的应用接口: ConcreteImplementor:实现Implementor. 三.UML类图 四.代码实现 4.1 桥接模式的实现代码 /// <summary> /// 实现 /// &

设计模式学习笔记-建造者模式

一.概述 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示: 二.模式中的角色 Builder:为创建一个Product对象的各个部件指定抽象接口: ConcreteBuilder:实现Builder的接口以构造和装配该产品的各个部件:定义并明确它所创建的表示:提供一个检索产品的接口: Director:构造一个使用Builder接口的对象: Product:表示被构造的复杂对象,ConcreteBuilder创建该产品的内部表示并定义它的装配过程:包含定义组成部件的类,

Java-马士兵设计模式学习笔记-桥接模式

一.概述 1.桥接模式的应用情况:(1)两个维度扩展(2)排列组合 二.代码 1.Gift.java 1 public class Gift { 2 3 protected GiftImpl giftImpl; 4 } 2.GiftImpl.java 1 public class GiftImpl { 2 3 } 3.WarmGift.java 1 public class WarmGift extends Gift { 2 3 public WarmGift(GiftImpl giftImpl

设计模式学习笔记--策略模式

定义: 策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式让算法独立于使用它的客户而独立变化. 我们在使用一些功能时,有时有很多种实现方法,或者多种结果,但是都有同样的使用方法,即调用接口,这就是策略模式. 例子: // 设计模式Demo.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> #include <string> using namespa

Java-马士兵设计模式学习笔记-命令模式

一.概述 命令模式 二.代码 1.Client.java 1 public class Client { 2 3 public void request(Server server){ 4 server.addCommand(new TextCommand()); 5 server.addCommand(new ImageCommand()); 6 server.doSomething(); 7 } 8 } 2.Server.java 1 public class Server { 2 3 pr