细说组合模式
提示:
博主:章飞 _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);
}
}
}
}
组合模式应用和注意事项
设计模式中的组合模式是部分-整体,树形结构的一种最典型的应用,只要涉及到树形结构的话,那么就推荐使用组合模式,如文件夹,树形菜单等等的管理上。
但是组合模式其实也有一个缺陷,即其对象的实例化的时候无法使用抽象类,而是直接使用了实现类,此种与依赖倒置的法则其实有点冲突,但是这种冲突并不影响组合模式的使用
欢迎继续访问,我的博客