设计模式之组合模式

我们平时在Android开发的过程中组合模式的应用并不多,组合模式更适合用于对一些界面ui的架构设计上,因此真正需要开发者去实现的不多。

  • 优点
    组合模式可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,它让高层模块忽略了层次的差异,方便对整个层次结构进行控制。
    高层模块可以一致地使用一个组合结构或其中单个对象,不必关心处理地是单个对象还是整个组合结构,简化了高层模块地代码。
    在组合结构中新增地枝干构件和叶子构件都很方便,无须对现有类库进行任何修改,符合“开闭原则”。
    组合模式为树形结构地面向对象实现提供了一种灵活地解决方案,通过叶子对象和枝干对象地递归组合,可以形成复杂地树形结构,但对树形结构地控制却非常简单。
  • 缺点
    在新增构件时不好对枝干中地构件类型进行限制,不能依赖类型系统来施加这些约束,因为在大多数情况下,它们都是来自于抽象层,此时,必须进行类型检查来实现,这个实现过程较为复杂。

说了这么多理论,现在我们亲自动手实现一个组合模式的案例。



import java.util.ArrayList;
import java.util.List;

public abstract class Dir {
    //声明一个list存储文件夹下的所有元素
    protected List<Dir> dirs = new ArrayList<Dir>();
    private String name;

    public Dir(String name){
        this.name = name;
    }

    public abstract void addDir(Dir dir);

    public abstract void rmDir(Dir dir);

    public abstract void clear();

    public abstract void print();

    public abstract List<Dir> getFiles();

    public String getName(){
        return name;
    }

}

import java.util.Iterator;
import java.util.List;

public class Folder extends Dir {
    public Folder(String name) {
        super(name);
    }

    @Override
    public void addDir(Dir dir) {
        dirs.add(dir);
    }

    @Override
    public void rmDir(Dir dir) {
        dirs.remove(dir);
    }

    @Override
    public void clear() {
        dirs.clear();
    }

    @Override
    public void print() {
        System.out.print(getName() + "(");
        Iterator<Dir> iter = dirs.iterator();
        while (iter.hasNext()) {
            Dir dir = iter.next();
            dir.print();
            if (iter.hasNext()) {
                System.out.print(", ");
            }
        }
        System.out.print(")");
    }

    @Override
    public List<Dir> getFiles() {
        return dirs;
    }
}

import java.util.List;

public class File extends Dir {

    public File(String name) {
        super(name);
    }

    @Override
    public void addDir(Dir dir) {
        throw new UnsupportedOperationException("不支持该操作");
    }

    @Override
    public void rmDir(Dir dir) {
        throw new UnsupportedOperationException("不支持该操作");
    }

    @Override
    public void clear() {
        throw new UnsupportedOperationException("不支持该操作");
    }

    @Override
    public void print() {
        System.out.print(getName());
    }

    @Override
    public List<Dir> getFiles() {
        throw new UnsupportedOperationException("不支持该操作");
    }
}

public class Client {
    public static void main(String[] args) {
        Dir disk = new Folder("C");
        disk.addDir(new File("aaa.txt"));

        Dir dirWin = new Folder("Windowx");
        dirWin.addDir(new File("xxx.txt"));
        disk.addDir(dirWin);

        disk.print();
    }
}

上面的案例就是一个典型的组合模式的写法,组合模式的核心个人认为是在于最开始的抽象类(即Dir类)的设计上,Folder和File只是继承了该抽象类进行不同的方法实现而已,在使用时使用多态的方法进行初始化。因此,采用组合模式进行代码设计时必须考虑好抽象方法,不然后面不是很好扩展。

组合模式在Android源码中的实现

在Android源码中有一处便使用到了组合模式——view和viewgroup的嵌套组合。有读过这部分代码的同学就会知道Android源码中的组合模式并不是像上面案例一样让viewgroup和view分别实现某个抽象类,他是让viewgroup继承view,然后将viewgroup特有的功能定义在viewparent和viewmanager这两个接口中。
需要注意的是viewgroup是抽象类。其将view中的onlayout方法重置为抽象方法,也就是说容器子类必须实现该方法来实现布局定位,我们知道对于view类该方法是一个空实现,因为对于一个普通的view来说该方法并没有什么实现价值,但是viewgroup就必须实现。除此之外,在view中比较重要的两个绘制流程的方法onMeasure和onDraw在viewgroup中都没有被重写,相对于onMeasure方法,在viewgroup中增加了一些计算子view的方法,如measureChildren、measureChildrenWithMargins等,而对于onDraw方法,viewgroup则定义一个dispatchDraw方法来调用其每一个子view的onDraw方法,因此,我们自定义viewgroup的时候可以不需要实现onDraw方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值