您的位置:首页 > 其它

设计模式学习--------1.组合模式学习

2013-07-13 12:55 309 查看
重新开始写博客 之前的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
}













                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  设计模式