美文网首页
Android源码设计模式学习笔记-组合模式

Android源码设计模式学习笔记-组合模式

作者: e小e | 来源:发表于2018-02-18 14:15 被阅读7次

    组合模式也是结构模式之一,组合模式比较简单,它将一组相似的对象看作一个对象处理,并根据一个树状结构来组合对象,然后提供一个统一的方法去访问相应的对象,以此忽略掉对象与对象之间的差别。它的UML图如下


    image.png

    下面是它的模版代码

    public abstract class Component {
        protected String name;
    
        public Component(String name) {
            this.name = name;
        }
    
        /**
         * 具体逻辑的方法由子类实现
         */
        public abstract void doSomething();
    }
    
    public class Composite extends Component{
    
        /**
         * 存储节点的容器
         * @param name
         */
        private List<Component> components = new ArrayList<>();
    
        public Composite(String name) {
            super(name);
        }
    
        @Override
        public void doSomething() {
            System.out.println(name);
            if (null != components){
                for (Component c : components){
                    c.doSomething();
                }
            }
        }
    
        /**
         * 添加子节点
         * @param child
         */
        public void addChild(Component child){
            components.add(child);
        }
    
        /**
         * 移除子节点
         * @param child
         */
        public void removeChild(Component child){
            components.remove(child);
        }
    
        /**
         * 获取子节点
         * @param index
         * @return
         */
        public Component getChildren(int index){
            return components.get(index);
        }
    }
    
    public class Leaf extends Component{
    
        public Leaf(String name) {
            super(name);
        }
    
        @Override
        public void doSomething() {
            System.out.print(name);
        }
    }
    
    public class Client {
        public static void main(String[] args){
            //构造一个根节点
            Composite root = new Composite("Root");
    
            //构造两个枝干节点
            Composite branch1 = new Composite("Branch1");
            Composite branch2 = new Composite("Branch2");
    
            //构造两个叶子节点
            Leaf leaf1 = new Leaf("Leaf1");
            Leaf leaf2 = new Leaf("Leaf2");
    
            //将叶子节点添加至枝干节点中
            branch1.addChild(leaf1);
            branch2.addChild(leaf2);
    
            //将枝干节点添加至根节点中
            root.addChild(branch1);
            root.addChild(branch2);
    
            //执行方法
            root.doSomething();
        }
    }
    

    角色介绍:
    Component : 抽象根节点,为组合中的对象声明接口。
    Composite : 定义有子节点的那些枝干节点的行为,存储子节点,在Component接口中实现与子节点有关的操作
    Leaf : 在组合中表示叶子节点对象
    Client : 通过Component接口操作组合节点的对象

    组合模式的简单实现

    下面我们以文件夹系统为例讲解一下组合模式的简单实现,整个文件夹系统如下所示


    image.png

    首先声明一个抽象类,表示文件或文件夹

    public abstract class Dir {
        /**
         * 声明一个List成员变量存储文件夹下的所有元素
         */
        protected List<Dir> dirs = new ArrayList<>();
    
        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;
        }
    }
    
    public class File extends Dir{
        public File(String name) {
            super(name);
        }
    
        @Override
        public void addDir(Dir dir) {
    
        }
    
        @Override
        public void rmDir(Dir dir) {
    
        }
    
        @Override
        public void clear() {
    
        }
    
        @Override
        public void print() {
    
        }
    
        @Override
        public List<Dir> getFiles() {
            return null;
        }
    }
    
    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;
        }
    }
    
    public class Client {
        public static void main(String[] args){
            //构造一个目录对象表示C盘根目录
            Dir diskC = new Folder("C");
    
            //C盘根目录下有一个文件ImbaMallLog.txt
            diskC.addDir(new File("ImbaMallLog.txt"));
    
            //C盘目录下还有3个子目录Windows,PrefLogs,Program File
            Dir dirWin = new Folder("Windows");
    
            //Windows目录下有文件explorer.exe
            dirWin.addDir(new File("explorer.exe"));
            diskC.addDir(dirWin);
    
            //PerfLogs目录
            Dir dirPer = new Folder("PerfLogs");
    
            //PerfLogs目录下有文件null.txt
            dirPer.addDir(new File("null.txt"));
            diskC.addDir(dirPer);
    
            //Program File 目录
            Dir dirPro = new Folder("Program File");
    
            //Program File 目录下有文件ftp.txt
            dirPro.addDir(new File("ftp.txt"));
            diskC.addDir(dirPro);
    
            //打印出文件结构
            diskC.print();
        }
    }
    
    Android源码中的模式实现

    在android中View和ViewGroup这种嵌套就是一种组合模式


    image.png

    为什么ViewGroup有容器的功能

    要回答这个问题,就要先了解View类与ViewGroup的差别在哪,首先要知道ViewGroup继承自View类

    public abstract class ViewGroup extends View implements ViewParent, ViewManager
    

    从继承角度来说ViewGroup拥有View类所有非私有化方法,既然如此,两者差别就在于ViewGroup所实现的ViewParent和ViewManager接口上,而事实也是如此,ViewManager接口定义了addView, removeView等对子视图操作的方法.

    public interface ViewManager{
        public void addView(View view, ViewGroup.LayoutParams params);
        public void updateViewLayout(View view, ViewGroup.LayoutParams params);
        public void removeView(View view);
    }
    

    ViewParent则定义了刷新容器的接口requestLayout和其它一些焦点事件的处理的接口.

    public interface ViewParent {
      public void requestLayout();
      public boolean isLayoutRequested();
      public void requestTransparentRegion(View child);
      public void invalidateChild(View child, Rect r);
      public ViewParent invalidateChildInParent(int[] location, Rect r);
      public ViewParent getParent();
      public void requestChildFocus(View child, View focused);
    }
    

    另外View中比较重要的两个测绘流程的方法onMeasure和onDraw在ViewGroup中都没有被重写,相对于onMeasure方法,在ViewGroup增加了一些计算子view的方法,如measureChildren,measureChildrenWithMargins等,而对于onDraw方法,ViewGroup定义了一个dispatchDraw方法来调用每一个子View的onDraw方法,由此可见,ViewGroup真的像一个容器一样,其职责只是负责对子元素的操作而非具体的个体行为.

    相关文章

      网友评论

          本文标题:Android源码设计模式学习笔记-组合模式

          本文链接:https://www.haomeiwen.com/subject/nqtbtftx.html