• 结构型模式之组合


    重新看组合/合成(Composite)模式,发现它并不像自己想象的那么简单,单纯从整体和部分关系的角度去理解还是不够的,并且还有一些通俗的模式讲解类的书,由于其举的例子太过“通俗”,以致让人理解产生偏差,不过设计模式本身就是一种程序设计思想,不同的人当然会产生具有偏差性质的理解。

    GOF对组合模式的定义是:将对象组合成树形结构以表示“部分 -整体”的层次结构。 Composite使得用户对单个对象和组合对象的使用具有一致性 。这里,“用户对单个对象和组合对象的使用具有一致性”,这是Composite模式产生的效果。从表示形式来看,Composite表示的是“部分-整体”的关系,但是,往往忽略了效果。下图是Composite模式的结构图:

    Composite模式的对象结果如下:

    Composite类提供对Leaf类对象的管理方法,如Add(),Remove(),GetChild()方法,这些方法的定义可以有两种方法:一个是放在Component的顶层父类中,这样所有的子类(包括Leaf类)都会集成该方法,但Leaf类可以选择不实现这些方法;另外一个是将对Leaf对象操作的方法放到Composite类中,并不是放到Component类中。现在以GOF所著书中所给的例子为例,写出组合模式的代码,类图结构如下:

    代码如下:

     1 abstract class Graphic{
     2     
     3     public void Draw(){}
     4     public void Add(Graphic g){}
     5     public void Remove(Graphic g){}
     6     public Graphic GetChild(int index){return null;}
     7 }
     8 class Line extends Graphic{
     9     public void Draw(){
    10         System.out.println("Draw a Line");
    11     }
    12 }
    13 class Rectange extends Graphic{
    14     public void Draw(){
    15         System.out.println("Draw a Rectange");
    16     }
    17 }
    18 class Text extends Graphic{
    19     public void Draw(){
    20         System.out.println("Draw a Text");
    21     }
    22 }
    23 class Picture extends Graphic{
    24     private Vector<Graphic> vec=new Vector<Graphic>();
    25     public void Draw(){
    26         for(Graphic g : vec){
    27             g.Draw();
    28         }
    29     }
    30     public void Add(Graphic g){
    31         vec.add(g);
    32     }
    33     public void Remove(Graphic g){
    34         try{
    35             vec.remove(g);
    36         }catch(Exception e){
    37             
    38         }
    39     }
    40     public Graphic GetChild(int index){
    41         return vec.get(index);
    42     }
    43 }
    44 public class Test{
    45     public static void main(String[] args){
    46         Picture p=new Picture();
    47         p.Add(new Text());
    48         p.Add(new Rectange());
    49         p.Add(new Line());
    50         p.Draw();
    51         }
    52 }
    View Code

    适用Composite模式的情况:

    1、想要表示对象的部分-整体层次结构

    2、希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。

    第一句话很好理解,第二句话该怎么理解呢?我的理解是,如果有一个方法Visist(Component con){con.Draw();}实现一个动作,这时候它并不需要知道是处理一个叶子结点对象还是一个组合对象,对于传进来的叶子结点对象,可以直接处理请求,如果是一个Composite,则将请求发给它的子部件,并且在转发请求之前/后还可以执行一些辅助操作。有人举过一个例子:文件和文件夹,该实现可以用组合模式,文件是Leaf,文件夹是Composite,我们可以单建文件对象,也可创建一个具有目录结构的文件夹对象,文件夹下面可以放文件对象,也可以放文件夹对象。

    为了提高系统的可复用性,有一些设计原则,其中有一条“组合/聚合复用原则”,就是优先使用“组合/聚合”,而非继承,这里说的组合是对象组合,也就是一个对象在运行时期动态获得其他对象的引用,从而达到不用继承而能扩展功能的效果;显然,对象组合的使用范围更大,和这里的组合模式不是同一个概念,前者毕竟是一个“设计原则”,而后者则是一个成型的“模式”,原则的使用范围当然更广了。

    通过今天的总结,对组合模式又有了进一步的认识,感谢GOF、《Java与模式》、《Thinking in Patterns》。

  • 相关阅读:
    小米官网中,鼠标移动到某个卡片,会轻轻上浮
    微信小程序之表单验证rule
    小程序调用自定义组件里的方法(this.selectComponent(#id))
    Git —— GitLab生产ssh密钥
    WX获取地理位置列表接口示例
    for...of语句在可迭代对象(包括 Array,Map,Set,String,TypedArray,arguments 对象等等)上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句(return break container可终止的循环)
    规格弹出框
    //将手机号中间4位数变成*
    //时间戳转换成日期时间(年月日)
    检查手机号是否正确
  • 原文地址:https://www.cnblogs.com/codeMedita/p/7354847.html
Copyright © 2020-2023  润新知