• 设计模式:组合(Composite)模式


    设计模式:组合(Composite)模式

    一、前言

      关于Composite模式,其实就是组合模式,又叫部分整体模式,这个模式在我们的生活中也经常使用,比如说如果读者有使用Java的GUI编写过程序的,肯定少不了定义一些组件,初始化之后,然后使用容器的add方法,将这些组件有顺序的组织成一个界面出来;或者读者如果编写过前端的页面,肯定使用过<div>等标签定义一些格式,然后格式之间互相组合,通过一种递归的方式组织成相应的结构,这种方式其实就是组合,将部分的组件镶嵌到整体之中;又或者文件和文件夹的组织关系,通过目录表项作为共同的特质(父类),一个文件夹可以包含多个文件夹和多个文件,一个文件容纳在一个文件夹之中。那么凭什么可以这样做呢,需要满足以下两点,首先整体的结构应该是一棵树,第二,所有的组件应该有一个共同的父类(有共同的本质),这个父类使得组件中的共同的本质可以提取出来(有了共同语言(父类)),进行互融,其实就是父类使用add方法,这样子类就可以通过抽象的方式通过父类来表达了,可能有点绕口,让我们看一个例子。

    二、代码

    Entry 抽象类:共同特质
     1 package zyr.dp.composite;
     2 
     3 public abstract class Entry {
     4     public abstract String getName();
     5     public abstract int getSize();
     6     public abstract void printList(String prefix);
     7     public  void printList(){
     8         printList("");
     9     }
    10     public  Entry add(Entry entry) throws RuntimeException{
    11         throw new RuntimeException();
    12     }
    13     public  String toString(){
    14         return getName()+"<"+getSize()+">";
    15     }
    16 }

      File 类:实现类,叶子结点

     1 package zyr.dp.composite;
     2 
     3 public class File extends Entry {
     4 
     5     private String name;
     6     private int size;
     7     public File(String name,int size){
     8         this.name=name;
     9         this.size=size;
    10     }
    11     public String getName() {
    12         return name;
    13     }
    14 
    15     public int getSize() {
    16         return size;
    17     }
    18 
    19     public void printList(String prefix) {
    20         System.out.println(prefix+"/"+this);
    21     }
    22 
    23 }
    Directory 类:可扩充节点(中间节点)
     1 package zyr.dp.composite;
     2 
     3 import java.util.ArrayList;
     4 import java.util.Iterator;
     5 
     6 public class Directory extends Entry {
     7 
     8     String name;
     9     ArrayList entrys=new ArrayList();
    10     public Directory(String name){
    11         this.name=name;
    12     }
    13     public String getName() {
    14         return name;
    15     }
    16 
    17     public int getSize() {
    18         int size=0;
    19         Iterator it=entrys.iterator();
    20         while(it.hasNext()){
    21             size+=((Entry)it.next()).getSize();
    22         }
    23         return size;
    24     }
    25 
    26     public Entry add(Entry entry) {
    27         entrys.add(entry);
    28         return this;
    29     }
    30     
    31     public void printList(String prefix) {
    32         System.out.println(prefix+"/"+this);
    33         Iterator it=entrys.iterator();
    34         Entry entry;
    35         while(it.hasNext()){
    36             entry=(Entry)it.next();
    37             entry.printList(prefix+"/"+name);
    38         }
    39     }
    40 
    41 }

      Main类:组合组件

    package zyr.dp.composite;
    
    public class Main {
    
        public static void main(String[] args) {
    
            Directory root=new Directory("根目录");
            
            Directory life=new Directory("我的生活");
            File eat=new File("吃火锅",100);
            File sleep=new File("睡觉",100);
            File study=new File("学习",100);
            life.add(eat);
            life.add(sleep);
            life.add(study);
            
            Directory work=new Directory("我的工作");
            File write=new File("写博客",200);
            File paper=new File("写论文",200);
            File homework=new File("写家庭作业",200);
            work.add(write);
            work.add(paper);
            work.add(homework);
            
            Directory relax=new Directory("我的休闲");
            File music=new File("听听音乐",200);
            File walk=new File("出去转转",200);
            relax.add(music);
            relax.add(walk);
            
            Directory read=new Directory("我的阅读");
            File book=new File("学习书籍",200);
            File novel=new File("娱乐小说",200);
            read.add(book);
            read.add(novel);
            
            root.add(life);
            root.add(work);
            root.add(relax);
            root.add(read);
    
            root.printList("D:");
            System.out.println("=================");
            work.printList("work");
            System.out.println("=================");
            novel.printList("novel");
            
    
        }
    
    }

     运行结果:

    三、总结

      由此可见,我们以前使用的“容器+内容”,其实是通过组合模式实现的,组合模式保证了容器和内容的一致性,容器里面可以套容器,也可以放内容,但是内容已经是叶子结点了,不能继续扩充,还记得我们在抽象工厂方式中使用的模式之中,为了将零件组装成产品,我们就使用了组合模式,非常的有意思,通过递归来遍历所有的内容。组合模式在我们的生活中使用的非常普遍,我们一定要使用好这个模式,理解其中的抽象,特别是add()的定义,抽象类和实现类之间的参数传递,这点至关重要,当然我们又使用了模板方法和迭代器,希望大家能明白模式之间的联系以及相互使用的道理。

      程序代码

  • 相关阅读:
    【shell】awk引用外部变量
    【shell】获取第10+个位置参数
    【ELK】Elasticsearch的备份和恢复
    【linux】crontab的环境变量问题
    【linux】如何给sudo的root设置环境变量
    【zabbix】自动注册,实现自动发现agent并添加监控(agent不需要任何配置)
    【windows】如何让一个程序开机自启动
    【linux】如何查看进程运行在那颗cpu上
    【Windows】修改远程桌面端口号
    分享知识-快乐自己:mongodb 安装部署(linux)
  • 原文地址:https://www.cnblogs.com/zyrblog/p/9237943.html
Copyright © 2020-2023  润新知