组合模式的应用
时间:2010-06-18 来源:yf956613
组合可以说是非常常见的一种结构,我们经常会遇到一些装配关系,从数据结构上来说,
这些关系往往表达为一种树状结构,这就用到了组合模式。
它的意图是,把对象组合成树形结构来来表示“部分-整体”关系,使得用户对单个对
象和组合对象的使用具有一致性。
1、结构
组合模式的结构可以有多种形式,一个最典型的结构如下。
2、效果
使用组合模式有以下优点:
1)组合对象可以由基本对象和其它组合对象构成,这样,采用有限的基本对象就可以
构造数量众多的组合对象。
2)组合对象和基本对象有相同的接口,这样操作组合对象和操作基本对象基本相同,
这样就可以大大简化客户代码。
3)可以很容易的增加类型,由于新类型符合相同的接口,因此不需要改动客户代码。
采用组合方式的代价是,由于组合对象和基本对象的接口相同,所以程序不能依赖具体
的类型,不过这个问题本身并不大。
3、组合模式的不同实现方式
组合模式可以有多种实现方式,下面列出三种。
1)强制类型集合
这里有自己定义一个表示控件聚合的 Metrics 对象,由这个对象放置类型(比如 Metric),
采用强制类型集合的优点为:
代码含义清楚:集合中的类型是确定的;
不容易出错:由于集合中的类型是确定的,所以有类型错误在编译的时候可以早期发现。
这种方式的缺点是需要自行定制集合,编码比较复杂。
2)基础节点和复合节点相同
这种方式集合就在基础节点中,便于构造复杂的数据结构。
3)非强制类型集合
非强制类型集合主要是采用象 ArrayList 这类集合,它的数据类型是 Object,因此可以保
留任何数据类型,由于.NET 中具备大量的可供选择的集合类,编码比较方便。
缺点是:
1)代码不够清晰,特别是 ArrayList 内部保留的数据结构往往看得不清楚。
2)需要进行类型转换,这样有些问题只有在运行中才会暴露出来,增加了调试的难度。
另外一个问题,组合模式往往需要遍历数据,这需要使用递归方法。
例:
package demo;
public class XMLMetric{
private String name;
public String getName(){
return name;
}
public void setName(String name){
this.name=name;
}
private String topage;
public String getTopage(){
return topage;
}
public void setTopage(String topage){
this.topage=topage;
}
private XMLMetric pmetric;
public XMLMetric getPmetric(){
return pmetric;
}
public void setPmetric(XMLMetric pmetric){
this.pmetric=pmetric;
}
private arrXMLMetric metrics;
public arrXMLMetric getMetrics(){
return metrics;
}
public void setMetrics(arrXMLMetric metrics){
this.metrics=metrics;
}
public XMLMetric(){
metrics=new arrXMLMetric();
}
class arrXMLMetric extends java.util.Vector{
public XMLMetric getXMLMetric(int idx){
return (XMLMetric)this.get(idx);
}
public void setXMLMetric(int idx,XMLMetric m){
this.add(idx,m);
}
public boolean Add(XMLMetric m){
return this.add(m);
}
public void Remove(XMLMetric m){
this.remove(m);
}
}
}
测试代码:
package demo;
public class Test {
public static void main(String[] args) {
XMLMetric1 m1=new XMLMetric1();
m1.setName("第一点 0.0");
XMLMetric2 m2=new XMLMetric2();
m2.setName("第二点 0.1");
m1.getMetrics().Add(m2);
XMLMetric1 m3=new XMLMetric1();
m3.setName("第三点 1.0");
m2.getMetrics().Add(m3);
XMLMetric2 m4=new XMLMetric2();
m4.setName("第四点 0.2");
m1.getMetrics().Add(m4);
XMLMetric1 m5=new XMLMetric1();
m5.setName("第五点 1.1");
m2.getMetrics().Add(m5);
XMLMetric2 m6=new XMLMetric2();
m6.setName("第六点 2.0");
m3.getMetrics().Add(m6);
Test m=new Test();
System.out.println(m1.getName());
m.addToTree(m1,0);
}
private void addToTree(XMLMetric c,int k){
//k 为当前层次数
for (int i=0;i<c.getMetrics().size();i++){
String s;
if (k==0) s="";
else if (k==1) s=" ";
else if (k==2) s=" ";
else if (k==3) s=" ";
else s="";
System.out.print(s+c.getMetrics().getXMLMetric(i).getName()+" : ");
//判断 c 是不是 XMLMetric1 或者 XMLMetric2 的一个实例
if (c instanceof XMLMetric1)
System.out.println(((XMLMetric1)c).hello());
else if (c instanceof XMLMetric2)
System.out.println(((XMLMetric2)c).hello());
else
System.out.println("原始行为");
//实现递归遍历
addToTree(c.getMetrics().getXMLMetric(i),k+1);
}
}
}
class XMLMetric1 extends XMLMetric{
public String hello(){
return "第一种行为";
}
}
class XMLMetric2 extends XMLMetric{
public String hello(){
return "第二种行为";
}
}
这些关系往往表达为一种树状结构,这就用到了组合模式。
它的意图是,把对象组合成树形结构来来表示“部分-整体”关系,使得用户对单个对
象和组合对象的使用具有一致性。
1、结构
组合模式的结构可以有多种形式,一个最典型的结构如下。
2、效果
使用组合模式有以下优点:
1)组合对象可以由基本对象和其它组合对象构成,这样,采用有限的基本对象就可以
构造数量众多的组合对象。
2)组合对象和基本对象有相同的接口,这样操作组合对象和操作基本对象基本相同,
这样就可以大大简化客户代码。
3)可以很容易的增加类型,由于新类型符合相同的接口,因此不需要改动客户代码。
采用组合方式的代价是,由于组合对象和基本对象的接口相同,所以程序不能依赖具体
的类型,不过这个问题本身并不大。
3、组合模式的不同实现方式
组合模式可以有多种实现方式,下面列出三种。
1)强制类型集合
这里有自己定义一个表示控件聚合的 Metrics 对象,由这个对象放置类型(比如 Metric),
采用强制类型集合的优点为:
代码含义清楚:集合中的类型是确定的;
不容易出错:由于集合中的类型是确定的,所以有类型错误在编译的时候可以早期发现。
这种方式的缺点是需要自行定制集合,编码比较复杂。
2)基础节点和复合节点相同
这种方式集合就在基础节点中,便于构造复杂的数据结构。
3)非强制类型集合
非强制类型集合主要是采用象 ArrayList 这类集合,它的数据类型是 Object,因此可以保
留任何数据类型,由于.NET 中具备大量的可供选择的集合类,编码比较方便。
缺点是:
1)代码不够清晰,特别是 ArrayList 内部保留的数据结构往往看得不清楚。
2)需要进行类型转换,这样有些问题只有在运行中才会暴露出来,增加了调试的难度。
另外一个问题,组合模式往往需要遍历数据,这需要使用递归方法。
例:
package demo;
public class XMLMetric{
private String name;
public String getName(){
return name;
}
public void setName(String name){
this.name=name;
}
private String topage;
public String getTopage(){
return topage;
}
public void setTopage(String topage){
this.topage=topage;
}
private XMLMetric pmetric;
public XMLMetric getPmetric(){
return pmetric;
}
public void setPmetric(XMLMetric pmetric){
this.pmetric=pmetric;
}
private arrXMLMetric metrics;
public arrXMLMetric getMetrics(){
return metrics;
}
public void setMetrics(arrXMLMetric metrics){
this.metrics=metrics;
}
public XMLMetric(){
metrics=new arrXMLMetric();
}
class arrXMLMetric extends java.util.Vector{
public XMLMetric getXMLMetric(int idx){
return (XMLMetric)this.get(idx);
}
public void setXMLMetric(int idx,XMLMetric m){
this.add(idx,m);
}
public boolean Add(XMLMetric m){
return this.add(m);
}
public void Remove(XMLMetric m){
this.remove(m);
}
}
}
测试代码:
package demo;
public class Test {
public static void main(String[] args) {
XMLMetric1 m1=new XMLMetric1();
m1.setName("第一点 0.0");
XMLMetric2 m2=new XMLMetric2();
m2.setName("第二点 0.1");
m1.getMetrics().Add(m2);
XMLMetric1 m3=new XMLMetric1();
m3.setName("第三点 1.0");
m2.getMetrics().Add(m3);
XMLMetric2 m4=new XMLMetric2();
m4.setName("第四点 0.2");
m1.getMetrics().Add(m4);
XMLMetric1 m5=new XMLMetric1();
m5.setName("第五点 1.1");
m2.getMetrics().Add(m5);
XMLMetric2 m6=new XMLMetric2();
m6.setName("第六点 2.0");
m3.getMetrics().Add(m6);
Test m=new Test();
System.out.println(m1.getName());
m.addToTree(m1,0);
}
private void addToTree(XMLMetric c,int k){
//k 为当前层次数
for (int i=0;i<c.getMetrics().size();i++){
String s;
if (k==0) s="";
else if (k==1) s=" ";
else if (k==2) s=" ";
else if (k==3) s=" ";
else s="";
System.out.print(s+c.getMetrics().getXMLMetric(i).getName()+" : ");
//判断 c 是不是 XMLMetric1 或者 XMLMetric2 的一个实例
if (c instanceof XMLMetric1)
System.out.println(((XMLMetric1)c).hello());
else if (c instanceof XMLMetric2)
System.out.println(((XMLMetric2)c).hello());
else
System.out.println("原始行为");
//实现递归遍历
addToTree(c.getMetrics().getXMLMetric(i),k+1);
}
}
}
class XMLMetric1 extends XMLMetric{
public String hello(){
return "第一种行为";
}
}
class XMLMetric2 extends XMLMetric{
public String hello(){
return "第二种行为";
}
}
相关阅读 更多 +