JAVA组合模式:先看看组合模式的定义:“将对象组合成树形结构以表示‘部分-整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。”
就拿剪发办卡的事情来分析一下吧。
首先,一张卡可以在总部,分店,加盟店使用,那么总部可以刷卡,分店也可以刷卡,加盟店也可以刷卡,这个属性结构的店面层级关系就明确啦。
那么,总店刷卡消费与分店刷卡消费是一样的道理,那么总店与分店对会员卡的使用也具有一致性。
1.组合模式的例子
那么组合模式的实例如下:
importjava.util.ArrayList; importjava.util.List; publicclassComponentDemo{ publicabstractclassComponent{ Stringname; publicabstractvoidadd(Componentc); publicabstractvoidremove(Componentc); publicabstractvoideachChild(); } //组合部件类 publicclassLeafextendsComponent{ //叶子节点不具备添加的能力,所以不实现 @Override publicvoidadd(Componentc){ //TODOAuto-generatedmethodstub System.out.println(""); } //叶子节点不具备添加的能力必然也不能删除 @Override publicvoidremove(Componentc){ //TODOAuto-generatedmethodstub System.out.println(""); } //叶子节点没有子节点所以显示自己的执行结果 @Override publicvoideachChild(){ //TODOAuto-generatedmethodstub System.out.println(name+"执行了"); } } //组合类 publicclassCompositeextendsComponent{ //用来保存节点的子节点 Listlist=newArrayList(); //添加节点添加部件 @Override publicvoidadd(Componentc){ //TODOAuto-generatedmethodstub list.add(c); } //删除节点删除部件 @Override publicvoidremove(Componentc){ //TODOAuto-generatedmethodstub list.remove(c); } //遍历子节点 @Override publicvoideachChild(){ //TODOAuto-generatedmethodstub System.out.println(name+"执行了"); for(Componentc:list){ c.eachChild(); } } } publicstaticvoidmain(String[]args){ ComponentDemodemo=newComponentDemo(); //构造根节点 CompositerootComposite=demo.newComposite(); rootComposite.name="根节点"; //左节点 CompositecompositeLeft=demo.newComposite(); compositeLeft.name="左节点"; //构建右节点,添加两个叶子几点,也就是子部件 CompositecompositeRight=demo.newComposite(); compositeRight.name="右节点"; Leafleaf1=demo.newLeaf(); leaf1.name="右-子节点1"; Leafleaf2=demo.newLeaf(); leaf2.name="右-子节点2"; compositeRight.add(leaf1); compositeRight.add(leaf2); //左右节点加入根节点 rootComposite.add(compositeRight); rootComposite.add(compositeLeft); //遍历组合部件 rootComposite.eachChild(); } }
执行结果如下:
2.应用组合模式的会员卡消费
那么我们就根据我们会员卡的消费,来模拟一下组合模式的实现吧!let'sGo!
首先:
1.我们的部件有,总店,分店,加盟店!
2.我们的部件共有的行为是:刷会员卡
3.部件之间的层次关系,也就是店面的层次关系是,总店下有分店、分店下可以拥有加盟店。
有了我们这几个必要条件后,我的要求就是目前店面搞活动当我在总店刷卡后,就可以累积相当于在所有下级店面刷卡的积分总额,设计的代码如下:
importjava.util.ArrayList; importjava.util.List; publicclassPayDemo{ publicabstractclassMarket{ Stringname; publicabstractvoidadd(Marketm); publicabstractvoidremove(Marketm); publicabstractvoidPayByCard(); } //分店下面可以有加盟店 publicclassMarketBranchextendsMarket{ //加盟店列表 Listlist=newArrayList(); publicMarketBranch(Strings){ this.name=s; } @Override publicvoidadd(Marketm){ //TODOAuto-generatedmethodstub list.add(m); } @Override publicvoidremove(Marketm){ //TODOAuto-generatedmethodstub list.remove(m); } //消费之后,该分店下的加盟店自动累加积分 @Override publicvoidPayByCard(){ //TODOAuto-generatedmethodstub System.out.println(name+"消费,积分已累加入该会员卡"); for(Marketm:list){ m.PayByCard(); } } } //加盟店下面不在有分店和加盟店,最底层 publicclassMarketJoinextendsMarket{ publicMarketJoin(Strings){ this.name=s; } @Override publicvoidadd(Marketm){ //TODOAuto-generatedmethodstub } @Override publicvoidremove(Marketm){ //TODOAuto-generatedmethodstub } @Override publicvoidPayByCard(){ //TODOAuto-generatedmethodstub System.out.println(name+"消费,积分已累加入该会员卡"); } } publicstaticvoidmain(String[]args){ PayDemodemo=newPayDemo(); MarketBranchrootBranch=demo.newMarketBranch("总店"); MarketBranchqhdBranch=demo.newMarketBranch("秦皇岛分店"); MarketJoinhgqJoin=demo.newMarketJoin("秦皇岛分店一海港区加盟店"); MarketJoinbtlJoin=demo.newMarketJoin("秦皇岛分店二白塔岭加盟店"); qhdBranch.add(hgqJoin); qhdBranch.add(btlJoin); rootBranch.add(qhdBranch); rootBranch.PayByCard(); } }
运行结果如下:
这样在累积所有子店面积分的时候,就不需要去关心子店面的个数了,也不用关系是否是叶子节点还是组合节点了,也就是说不管是总店刷卡,还是加盟店刷卡,都可以正确有效的计算出活动积分。
3.什么情况下使用组合模式
引用大话设计模式的片段:当发现需求中是体现部分与整体层次结构时,以及你希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑组合模式了。