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


    重新开始写博客 之前的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
    }


    
    
  • 相关阅读:
    vue_组件化开发
    C++ / C# 访问网络共享文件夹
    PetaLinux 设置操作系统内存
    linux 不用./ 直接执行程序
    Visual Studio Code 开发环境搭建 —— C# 扩展插件
    Visual Studio Code 调试项目时传参
    PetaLinux 安装
    Ubuntu 报 "xxx is not in the sudoers file.This incident will be reported" 错误解决方法
    常用 Linux 命令
    搭建 Git 服务器(Ubuntu 系统)
  • 原文地址:https://www.cnblogs.com/krislight1105/p/3748377.html
Copyright © 2020-2023  润新知