【设计模式十八之组合模式】组合模式

细说组合模式

提示:
博主:章飞 _906285288的博客
博客地址:http://blog.csdn.net/qq_29924041


细说组合模式

组合模式的使用在生活中也非常广泛,而且在组合模式中,最主要关联的数据结构莫过于树形结构,有根节点,树枝节点以及树叶节点等等。翻开书的目录结构想想,是不是一种树形结构,有一级目录,二级目录,手机文档管理器中,是不是有根目录,有子目录,乃至到具体的文件类型。你所在公司的架构图是不是也是树形结构,有总经办,开发部,财务部,再到具体的员工,所以,组合模式的使用是为了契合这样一种设计模式而生的

定义

组合模式Composite Pattern:也叫做合成模式,有时也叫做部分-整体(Part-Whole),主要是用来描述部分与整体之间的关系的一种设计模式。它是一种将对象组合成树形结构,用来表示部分-整体的层次的一种设计模式,使得用户对单个对象或者组合对象的使用具有一致性)

UML模型

在这里插入图片描述
在组合设计模式中主要包含了以下的一些角色:
1:Component 组件部分,即定义了参加组合设计模式对象的共有方法和属性,即无论是组合对象,还是叶子对象,他们的共有特性部分抽象出来
2:Leaf 叶子对象,其下是没有任何分支的,是遍历出来的最小的单位
3:Composite 组合对象,即树枝对象,它的作用是组合树枝节点和叶子节点形成一个树形
4:Client 构建部分对象,也就是测试对象而已

注意:在构建树形对象的时候,往往是双向的,即树枝节点中可以遍历出所有的子节点,但是也需要通过子节点能够获知树节点的类型。这一点相对来说也比较重要

场景

场景一

设计模式之禅中的案例,打造一个公司的树形架构,公司有ceo,研发部,市场部,财务部,研发部下面又分成了研发一组,研发二组,以及员工类型,通过层层的组合,形成了公司现有的规模。参考代码一

场景二

一本书是有目录的吧,目录分为一级目录,二级目录,那就拿设计模式这本书来举例,一级目录为设计模式,设计模式下又分为设计模式分类,设计模式思想,设计模式分类下为具体的设计模式如单例模式,工厂模式等等,设计模式思想下分为单一职责,里式替换等等思想。从而可以组合成一个完整的目录结构

代码

代码一
package src.com.zzf.designpattern.compositepattern.demo3;

/**
 * 定义一个抽象的员工类
 * @author zhouzhangfei
 *
 */
public abstract class Corp {
	//员工姓名
	private String name = "";
	//员工的职位
	private String position = "";
	//员工薪水
	private int salary = 0;
	//员工的上司是谁
	private Corp parent = null;

	public Corp(String _name, String _position, int _salary) {
		this.name = _name;
		this.position = _position;
		this.salary = _salary;
	}

	public String getInfo() {
		String info = "";
		info = "姓名:" + this.name;
		info = info + "\t职位:" + this.position;
		info = info + "\t薪水:" + this.salary;
		return info;
	}

	protected void setParent(Corp _parent) {
		this.parent = _parent;
	}

	public Corp getParent() {
		return this.parent;
	}
}

package src.com.zzf.designpattern.compositepattern.demo3;

import java.util.ArrayList;


public class Branch extends Corp {
	
	private ArrayList subordinateList = new ArrayList<>();

	public Branch(String _name, String _position, int _salary) {
		super(_name, _position, _salary);
		// TODO Auto-generated constructor stub
	}

	// 增加一个下属,可能是小头目,也可能是个小兵
	public void addSubordinate(Corp corp) {
		corp.setParent(this);
		this.subordinateList.add(corp);
	}

	// 我有哪些下属
	public ArrayList<Corp> getSubordinate() {
		return this.subordinateList;
	}

}

package src.com.zzf.designpattern.compositepattern.demo3;

public class Leaf extends Corp{

	public Leaf(String _name, String _position, int _salary) {
		super(_name, _position, _salary);
		// TODO Auto-generated constructor stub
	}

}

package src.com.zzf.designpattern.compositepattern.demo3;

import java.util.ArrayList;


public class Client {
	public static void main(String[] args) {
		//首先是组装一个组织结构出来
		Branch ceo = compositeCorpTree();
		//首先把CEO的信息打印出来:
		System.out.println(ceo.getInfo());
		//然后是所有员工信息
		System.out.println(getTreeInfo(ceo));
		System.out.println("----------");
	}

	// 把整个树组装出来
	public static Branch compositeCorpTree() {
		// 首先产生总经理CEO
		Branch root = new Branch("王大麻子", "总经理", 100000);
		// 把三个部门经理产生出来
		Branch developDep = new Branch("刘大瘸子", "研发部门经理", 10000);
		Branch salesDep = new Branch("马二拐子", "销售部门经理", 20000);
		Branch financeDep = new Branch("赵三驼子", "财务部经理", 30000);
		// 再把三个小组长产生出来
		Branch firstDevGroup = new Branch("杨三乜斜", "开发一组组长", 5000);
		Branch secondDevGroup = new Branch("吴大棒槌", "开发二组组长", 6000);
		// 把所有的小兵都产生出来
		Leaf a = new Leaf("a", "开发人员", 2000);
		Leaf b = new Leaf("b", "开发人员", 2000);
		Leaf c = new Leaf("c", "开发人员", 2000);
		Leaf d = new Leaf("d", "开发人员", 2000);
		Leaf e = new Leaf("e", "开发人员", 2000);
		Leaf f = new Leaf("f", "开发人员", 2000);
		Leaf g = new Leaf("g", "开发人员", 2000);
		Leaf h = new Leaf("h", "销售人员", 5000);
		Leaf i = new Leaf("i", "销售人员", 4000);
		Leaf j = new Leaf("j", "财务人员", 5000);
		Leaf k = new Leaf("k", "CEO秘书", 8000);
		Leaf zhengLaoLiu = new Leaf("郑老六", "研发部副经理", 20000);
		// 开始组装
		// CEO下有三个部门经理和一个秘书
		root.addSubordinate(k);
		root.addSubordinate(developDep);
		root.addSubordinate(salesDep);
		root.addSubordinate(financeDep);
		// 研发部经理
		developDep.addSubordinate(zhengLaoLiu);
		developDep.addSubordinate(firstDevGroup);
		developDep.addSubordinate(secondDevGroup);
		// 看看开发两个开发小组下有什么
		firstDevGroup.addSubordinate(a);
		firstDevGroup.addSubordinate(b);
		firstDevGroup.addSubordinate(c);
		secondDevGroup.addSubordinate(d);
		secondDevGroup.addSubordinate(e);
		secondDevGroup.addSubordinate(f);
		// 再看销售部下的人员情况
		salesDep.addSubordinate(h);
		salesDep.addSubordinate(i);
		// 最后一个财务
		financeDep.addSubordinate(j);
		
		return root;
	}

	public static String getTreeInfo(Branch root) {
		ArrayList<Corp> subordinateList = root.getSubordinate();
		String info = "";
		for (Corp s : subordinateList) {
			if (s instanceof Leaf) { // 是员工就直接获得信息
				info = info + s.getInfo() + "\n";
			} else { // 是个小头目
				info = info + s.getInfo() + "\n" + getTreeInfo((Branch) s);
			}
		}
		return info;
	}
}

代码二
package src.com.zzf.designpattern.compositepattern.demo5;

public abstract class Catalog {
	public String catalogName;
	private Catalog parentCatalog;
	
	public Catalog(String _catalogName){
		this.catalogName = _catalogName;
	}
	
	public void getCatalogInfo(){
		System.out.println("catalogName:"+catalogName);
	}
	
	public void setParent(Catalog _parentCatalog){
		this.parentCatalog = _parentCatalog;
	}
	
	public Catalog getParentCatalog(){
		return parentCatalog;
	}
	
}

package src.com.zzf.designpattern.compositepattern.demo5;

import java.util.ArrayList;

public class CompositeCatalog extends Catalog{
	private ArrayList<Catalog> mArrayList = new ArrayList<>();
	
	public CompositeCatalog(String _catalogName) {
		super(_catalogName);
		// TODO Auto-generated constructor stub
	}
	
	public void addCatalog(Catalog _mCatalog){
		_mCatalog.setParent(this);
		mArrayList.add(_mCatalog);
	}
	
	public ArrayList<Catalog> getChildCatalogs(){
		return mArrayList;
	}

}

package src.com.zzf.designpattern.compositepattern.demo5;

public class LeafCatalog extends Catalog{

	public LeafCatalog(String _catalogName) {
		super(_catalogName);
		// TODO Auto-generated constructor stub
	}

}

package src.com.zzf.designpattern.compositepattern.demo5;


public class Client {
	public static void main(String[] args) {
		CompositeCatalog catalog = (CompositeCatalog) compositeCataLogDatas();
		System.out.println(catalog.catalogName);
		display(catalog);
	}
	
	private static Catalog compositeCataLogDatas(){
		CompositeCatalog rootCataLog = new CompositeCatalog("设计模式");
		CompositeCatalog typeCataLog = new CompositeCatalog("设计模式分类");
		CompositeCatalog catalogThought = new CompositeCatalog("设计模式思想");
		
		LeafCatalog leafCatalog = new LeafCatalog("策略模式");
		LeafCatalog leafCatalog2 = new LeafCatalog("代理模式");
		LeafCatalog leafCatalog3 = new LeafCatalog("单例模式");
		LeafCatalog leafCatalog4 = new LeafCatalog("多例模式");
		LeafCatalog leafCatalog5 = new LeafCatalog("工厂方法模式");
		LeafCatalog leafCatalog6 = new LeafCatalog("抽象工厂模式");
		LeafCatalog leafCatalog7 = new LeafCatalog("门面模式");
		LeafCatalog leafCatalog8 = new LeafCatalog("适配器模式");
		LeafCatalog leafCatalog9 = new LeafCatalog("模板方法模式");
		LeafCatalog leafCatalog10 = new LeafCatalog("建造者模式");
		LeafCatalog leafCatalog11 = new LeafCatalog("桥梁模式");
		LeafCatalog leafCatalog12 = new LeafCatalog("命令模式");
		LeafCatalog leafCatalog13 = new LeafCatalog("装饰模式");
		LeafCatalog leafCatalog14 = new LeafCatalog("迭代器模式");
		LeafCatalog leafCatalog15 = new LeafCatalog("组合模式");
		LeafCatalog leafCatalog16 = new LeafCatalog("观察者模式");
		LeafCatalog leafCatalog17 = new LeafCatalog("责任链模式");
		LeafCatalog leafCatalog18 = new LeafCatalog("访问者模式");
		LeafCatalog leafCatalog19 = new LeafCatalog("状态模式");
		LeafCatalog leafCatalog20 = new LeafCatalog("原型模式");
		LeafCatalog leafCatalog21 = new LeafCatalog("中介者模式");
		LeafCatalog leafCatalog22 = new LeafCatalog("解释器模式");
		LeafCatalog leafCatalog23 = new LeafCatalog("享元模式");
		LeafCatalog leafCatalog24 = new LeafCatalog("备忘录模式");
		
		LeafCatalog leafCatalog31 = new LeafCatalog("单一职责");
		LeafCatalog leafCatalog32 = new LeafCatalog("里式替换");
		LeafCatalog leafCatalog33 = new LeafCatalog("依赖倒置");
		LeafCatalog leafCatalog34 = new LeafCatalog("接口隔离");
		LeafCatalog leafCatalog35 = new LeafCatalog("迪米特法则");
		LeafCatalog leafCatalog36 = new LeafCatalog("开闭原则");
		
		rootCataLog.addCatalog(typeCataLog);
		rootCataLog.addCatalog(catalogThought);
		
		typeCataLog.addCatalog(leafCatalog);
		typeCataLog.addCatalog(leafCatalog2);
		typeCataLog.addCatalog(leafCatalog3);
		typeCataLog.addCatalog(leafCatalog4);
		typeCataLog.addCatalog(leafCatalog5);
		typeCataLog.addCatalog(leafCatalog6);
		typeCataLog.addCatalog(leafCatalog7);
		typeCataLog.addCatalog(leafCatalog8);
		typeCataLog.addCatalog(leafCatalog9);
		typeCataLog.addCatalog(leafCatalog10);
		typeCataLog.addCatalog(leafCatalog11);
		typeCataLog.addCatalog(leafCatalog12);
		typeCataLog.addCatalog(leafCatalog13);
		typeCataLog.addCatalog(leafCatalog14);
		typeCataLog.addCatalog(leafCatalog15);
		typeCataLog.addCatalog(leafCatalog16);
		typeCataLog.addCatalog(leafCatalog17);
		typeCataLog.addCatalog(leafCatalog18);
		typeCataLog.addCatalog(leafCatalog19);
		typeCataLog.addCatalog(leafCatalog20);
		typeCataLog.addCatalog(leafCatalog21);
		typeCataLog.addCatalog(leafCatalog22);
		typeCataLog.addCatalog(leafCatalog23);
		typeCataLog.addCatalog(leafCatalog24);
		
		catalogThought.addCatalog(leafCatalog31);
		catalogThought.addCatalog(leafCatalog32);
		catalogThought.addCatalog(leafCatalog33);
		catalogThought.addCatalog(leafCatalog34);
		catalogThought.addCatalog(leafCatalog35);
		catalogThought.addCatalog(leafCatalog36);
		
		return rootCataLog;
	}
	
	public static void display(CompositeCatalog root) {
		for(Catalog c:root.getChildCatalogs()){ 
			if(c instanceof LeafCatalog){ //
				c.getCatalogInfo();
			}else{ //
				System.out.println(c.catalogName);
				display((CompositeCatalog) c);
			}
		}
	}
}

基于UML的代码
package src.com.zzf.designpattern.compositepattern.demo4;

/**
 * 树枝节点和树叶共同抽象出来的抽象特性
 * @author zhouzhangfei
 *
 */
public abstract class Component {
	public void dosomthing(){
		
	}
}

package src.com.zzf.designpattern.compositepattern.demo4;

import java.util.ArrayList;

/**
 * 容器对象,即树枝节点或者根节点对象
 * @author zhouzhangfei
 *
 */
public class Composite extends Component {
	// 构建容器
	private ArrayList<Component> componentArrayList = new ArrayList<Component>();
	// 添加一个叶子或者树枝节点

	public void add(Component component) {
		this.componentArrayList.add(component);
	}

	// 移除一个叶子或者树枝节点
	public void remove(Component component) {
		this.componentArrayList.remove(component);
	}

	//获取当前节点下的所有子节点
	public ArrayList<Component> getChildren() {
		return this.componentArrayList;
	}
}

package src.com.zzf.designpattern.compositepattern.demo4;

/**
 * 叶子节点,即组合模式中能够遍历出来的最小单元
 * @author zhouzhangfei
 *
 */
public class Leaf extends Component{
	@Override
	public void dosomthing() {
		// TODO Auto-generated method stub
		System.out.println(this.hashCode()+"doSomething");
	}
}

package src.com.zzf.designpattern.compositepattern.demo4;

public class Client {
	public static void main(String[] args) {
		//创建一个根节点
		Composite root = new Composite(); 
		root.dosomthing();
		//创建树枝节点
		Composite branch = new Composite();
		//创建叶子几点
		Leaf leaf = new Leaf();
		//添加树枝节点
		root.add(branch);
		//树枝节点添加叶子节点
		branch.add(leaf);
		display(root);
	}

	public static void display(Composite root) {
		for(Component c:root.getChildren()){ 
			if(c instanceof Leaf){ 
				c.dosomthing();
			}else{ 
				display((Composite)c);
			}
		}
	}
	
}

组合模式应用和注意事项

设计模式中的组合模式是部分-整体,树形结构的一种最典型的应用,只要涉及到树形结构的话,那么就推荐使用组合模式,如文件夹,树形菜单等等的管理上。
但是组合模式其实也有一个缺陷,即其对象的实例化的时候无法使用抽象类,而是直接使用了实现类,此种与依赖倒置的法则其实有点冲突,但是这种冲突并不影响组合模式的使用




欢迎继续访问,我的博客
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值