重新开始写博客 之前的JAVA博客一直没更新,一直忙,连地址都忘了,现在下定决心重新拾起。一边学习android 一边温习java基础。现在明白忙只是借口,真正的原因是因为太懒了,肯定能挤出时间学习总结,至少每周末会写一到两篇学习总结,下定决心坚持下来,恩,为自己加油。
-------------------------------------------------------------------
Android中对组合模式的应用,可谓是泛滥成粥,随处可见,那就是View和View Group类的使用。在android UI设计,几乎所有的widget和布局类都依靠这两个类。
考虑一个应用:
商品类别树
服装
男装: 衬衣 西服
女装:裙子 套装
不用组合模式实现:
将服装看成根节点,男装和女装是树枝节点,衬衣等是叶子节点。根节点和树枝节点都可以包括叶子节点,所以看成一个组合类。
叶子节点定义:
package com.light.com; public class Leaf { private String name = ""; public Leaf() { } public Leaf(String name) { this.name = name; } @Override public String toString() { return name; } }
组合类定义:
package com.light.com; import java.util.ArrayList; import java.util.List; public class Composite { private List<Composite> composites = new ArrayList<Composite>(); private List<Leaf> leafs = new ArrayList<Leaf>(); private String name = ""; public Composite() {} public Composite(String name) { this.name = name; } //添加树枝 public void addComposite(Composite childComposite){ composites.add(childComposite); } //添加叶子 public void addLeaf(Leaf leaf){ leafs.add(leaf); } @Override public String toString() { StringBuffer sb = new StringBuffer("+"); sb.append(this.name+" "); for(Composite c :composites){ sb.append(c.toString()); } sb.append(" "); for(Leaf l:leafs){ sb.append(l.toString()+" "); } return sb.toString(); } }
客户端:
package com.light.com; public class Client { public static void main(String[] args) { Composite root = new Composite("服装"); Composite male = new Composite("男装"); Composite female = new Composite("女装"); Leaf shirt = new Leaf("衬衣"); Leaf jack = new Leaf("夹克"); Leaf dress = new Leaf("裙子"); Leaf coat = new Leaf("套装"); root.addComposite(male); root.addComposite(female); male.addLeaf(shirt); male.addLeaf(jack); female.addLeaf(dress); female.addLeaf(coat); System.out.println(root); } }
输出结果:
+服装
+男装 -衬衣 -夹克
+女装 -裙子 -套装
有何问题:
需要区别对待组合对象和叶子对象。当叶子节点和树枝节点增多时,程序变的复杂,扩展性不强
引入组合模式
解决方案:
定义一个抽象类。既可以代表叶子对象也可以代表组合对象。
抽象类:
package com.light.com; public abstract class Component { public abstract void doSomething(); public void addChild(Component component) { // 缺省实现抛异常,叶子对象没有这个功能 throw new UnsupportedOperationException("不支持这个功能"); } public void removeChild(Component component) { // 缺省实现抛异常,叶子对象没有这个功能 throw new UnsupportedOperationException("不支持这个功能"); } public Component getChildren(int index){ // 缺省实现抛异常,叶子对象没有这个功能 throw new UnsupportedOperationException("不支持这个功能"); } }
组件类:
package com.light.com; import java.util.ArrayList; import java.util.List; public class Composite extends Component { private List<Component> components = null; private String name; public Composite() { } public Composite(String name) { this.name = name; } @Override public void doSomething() { //打印自己的名字 System.out.println("+"+this.name); if (components != null) { System.out.print(" "); for (Component c : components) { //递归 c.doSomething(); System.out.print(" "); } System.out.println(); } } @Override public void addChild(Component component) { if (components == null) { components = new ArrayList<Component>(); } components.add(component); } @Override public void removeChild(Component component) { if (components != null) { components.remove(component); } } @Override public Component getChildren(int index) { if (components != null) { if (index >= 0 && index < components.size()) { components.get(index); } } return null; } }
叶子类:
package com.light.com; public class Leaf extends Component{ private String name = ""; public Leaf() { } public Leaf(String name) { this.name = name; } @Override public void doSomething() { //打印自己的名字 System.out.print("-"+this.name); } }
客户端:
package com.light.com; public class Client { public static void main(String[] args) { Component root = new Composite("服装"); Component male = new Composite("男装"); Component female = new Composite("女装"); Component shirt = new Leaf("衬衣"); Component jack = new Leaf("夹克"); Component dress = new Leaf("裙子"); Component coat = new Leaf("套装"); root.addChild(male); root.addChild(female); male.addChild(shirt); male.addChild(jack); female.addChild(dress); female.addChild(coat); root.doSomething(); } }
输出结果:
+服装
+男装 -衬衣 -夹克
+女装 -裙子 -套装
优点:
让客户端不再区分操作的是组合对象还是叶子对象,而是统一操作组件对象。增加了透明性
缺点:
客户端可能会调用叶子节点中的无用方法 抛出异常。牺牲了安全性。
考虑两个问题:
1.如果删除某个商品类别。如果这个类别没有子类别直接删除即可。但它若有子类别,一种是需要连带删除其子类另一种是将其子类别上移一层。
2.如果进行商品细化和整理,把原本A类别下得子类别移动到B类别下,需连带其子类一起移动。
问题解决方案:
在组合对象添加子组件对象时,为子组件对象设置父组件的引用,这样就可以在删除或移动时,将父组件的引用重新设置。把这些实现放到抽象类中
改进后的抽象类:
package com.light.com; import java.util.List; public abstract class Component { //记录父组件对象 private Component parent; public Component getParent() { return parent; } public void setParent(Component parent) { this.parent = parent; } public List<Component> getChildren(){ // 缺省实现抛异常,叶子对象没有这个功能 throw new UnsupportedOperationException("不支持这个功能"); } public abstract void doSomething(); public void addChild(Component component) { // 缺省实现抛异常,叶子对象没有这个功能 throw new UnsupportedOperationException("不支持这个功能"); } public void removeChild(Component component) { // 缺省实现抛异常,叶子对象没有这个功能 throw new UnsupportedOperationException("不支持这个功能"); } public Component getChildren(int index){ // 缺省实现抛异常,叶子对象没有这个功能 throw new UnsupportedOperationException("不支持这个功能"); } }
改进后的组件类:
package com.light.com; import java.util.ArrayList; import java.util.List; public class Composite extends Component { private List<Component> components = null; private String name; public Composite() { } public Composite(String name) { this.name = name; } @Override public List<Component> getChildren() { return components; } @Override public void doSomething() { //打印自己的名字 System.out.println("+"+this.name); if (components != null) { System.out.print(" "); for (Component c : components) { //递归 c.doSomething(); } System.out.println(); } } @Override public void addChild(Component component) { if (components == null) { components = new ArrayList<Component>(); } components.add(component); //设置其为父类对象 component.setParent(this); } @Override public void removeChild(Component component) { if (components != null) { //查找要删除组件的索引位置 int idx = components.indexOf(component); //如果删除的为子组件类别 if(idx!=-1){ //将该子组件下的组件的父类别设置为其原来的父类别,刘备托孤给诸葛亮,诸葛亮设置成了刘禅的父类。 for(Component c:component.getChildren()){ c.setParent(this); components.add(c); } } //再将其删除,刘备挂了 components.remove(idx); } } @Override public Component getChildren(int index) { if (components != null) { if (index >= 0 && index < components.size()) { components.get(index); } } return null; } }
叶子类无变化。
客户端:
package com.light.com; public class Client { public static void main(String[] args) { Component root = new Composite("服装"); Component male = new Composite("男装"); Component female = new Composite("女装"); Component shirt = new Leaf("衬衣"); Component jack = new Leaf("夹克"); Component dress = new Leaf("裙子"); Component coat = new Leaf("套装"); root.addChild(male); root.addChild(female); male.addChild(shirt); male.addChild(jack); female.addChild(dress); female.addChild(coat); root.doSomething(); root.removeChild(male); root.doSomething(); } }
输出结果:
+服装
+男装 -衬衣 -夹克
+女装 -裙子 -套装
+服装
+女装 -裙子 -套装
-衬衣 -夹克
---------------------------------------------------
android中组合模式的实现
牺牲了透明性 增加了安全性
View类的实现:
public class View{ //... ... //省略了无关的方法 }
ViewGroup类的实现:
public abstract class ViewGroup extends View{ /** * Adds a child view. */ public void addView(View child) { //... } public void removeView(View view) { //... } /** * Returns the view at the specified position in the group. */ public View getChildAt(int index) { try { return mChildren[index]; } catch (IndexOutOfBoundsException ex) { return null; } } //other methods }