投稿    登录
欢迎加入Nice Coder,与众多Coder分享经验,群号:530244901

【原创】设计模式系列(二十一)——组合模式和迭代器模式

设计之道 wjx@admin.cc 133浏览 0评论

组合模式

概念:

      把多个对象组成树状结构来表示局部与整体,这样用户可以一样的对待单个对象和对象的组合。(维基百科)

理解概念:

      多个对象组成树状结构,树结构中有根节点,树枝节点,叶子节点之分,概念中说利用组合模式可以等同对待单个对象和对象的组合,单个对象在其中的表现就是叶子节点,或者某个单个的树枝节点,或者单个的根节点,对象的组合则表现为某棵子树或者一整个树,我们来看一下是怎么做到的。

应用场景:

      我们想象以下场景,java君的餐厅有各种各样的菜品,四大菜系应有尽有。下面是菜品和菜系关系图的一部分

餐厅从全国各地请了名厨,看一下上面这个关系图,根节点是菜谱,整个菜谱下分为四大菜系,鲁菜下分为济南菜和孔府菜,每个菜系下都有一个代表性的菜品,糖醋鲤鱼,一品豆腐,鱼香肉丝,煲仔饭,扬州炒饭,当然不止这些,说了只是一部分而已。我们来通过代码去构建这棵树。直接用组合模式。

package combination;

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

/**
 * Created by 17854 on 2016/11/16.
 */
abstract class Dish
{
    private String name;
    public Dish(String name)
    {
        this.name = name;
    }
    public String getInfo()
    {
        return this.name;
    }
}
class ConcreteDish extends Dish//具体的菜
{
    public ConcreteDish(String name)
    {
        super(name);
    }
}
class DishesSeries extends Dish//菜系
{
    private List<Dish> dishs = new ArrayList<>();
    public DishesSeries(String name)
    {
        super(name);
    }
    public void add(Dish dish)
    {
        this.dishs.add(dish);
    }
    public void remove(Dish dish)
    {
        this.dishs.remove(dish);
    }
    public List<Dish> getChildren()
    {
        return dishs;
    }
}
public class Client
{
    public static void main(String[] args)
    {
        DishesSeries root = new DishesSeries("菜谱");
        DishesSeries lu = new DishesSeries("鲁菜");
        DishesSeries chuan = new DishesSeries("川菜");
        DishesSeries yue = new DishesSeries("粤菜");
        DishesSeries huaiYang = new DishesSeries("淮扬菜");
        DishesSeries jiNan = new DishesSeries("济南菜");
        DishesSeries kongFu = new DishesSeries("孔府菜");
        root.add(lu);
        root.add(chuan);
        root.add(yue);
        root.add(huaiYang);
        lu.add(jiNan);
        lu.add(kongFu);
        jiNan.add(new ConcreteDish("糖醋鲤鱼"));
        kongFu.add(new ConcreteDish("一品豆腐"));
        chuan.add(new ConcreteDish("鱼香肉丝"));
        yue.add(new ConcreteDish("煲仔饭"));
        huaiYang.add(new ConcreteDish("扬州炒饭"));
        show(root);
    }
    public static void show(DishesSeries series)
    {
        System.out.println(series.getInfo());
        series.getChildren().forEach(child->{
            if(child instanceof DishesSeries)
            {
                show((DishesSeries) child);
            }else
                System.out.println(child.getInfo());
        });
    }
}

以上就是所谓的组合模式,很简单,我们对一开始的那个树进行分析,这课数有叶子节点和树枝节点,他们的共同之处是我们都要获取他们的信息,树枝节点比叶子节点多的东西是有一个孩子节点的定义,所以我们定义了一个Dish抽象类,其中有getInfo方法,这是叶子和树枝的共有方法。在叶子节点中没有实现其他的方法,我们当然可以覆盖getInfo方法,在树枝节点中,我们添加了一个List类型的Children属性,然后添加了添加子节点,删除子节点,获取子节点列表的方法。这就是一个组合模式的应用,把这些对象表示成了部分-整体结构。我们定义了一个静态的方法,来对这棵树进行遍历、我们只需要知道根节点就能知道所有的其他的对象,这样,我们就把单个对象和组合起来的对象等同对待。

提炼总结:

      组合模式是一种很常见的模式。使用该模式,对于高层模块来说,调用局部的元素和调用整体的元素,没有任何区别。高层模块不用关心这是一个单个对象还是一个组合结构,而且,在这个设计下,我们很容易进行节点的扩展。方便维护。但是他的缺点也很明显,不符合依赖倒置原则。我们在进行构造的时候,对于树枝节点和叶子节点,需要声明为具体的类来进行构造,对于这种情况,我们可以使用所谓透明的组合模式,就是在原生的组合模式的基础上,完全抹去叶子节点和树枝节点的区别,所有的节点不分是叶子还是树枝。都有孩子节点这一个属性,只不过孩子节点个数是0的时候,就认为他是一个叶子节点。这种模式如果处理不好,很容易出现安全问题。我们通常把区分叶子节点和树枝节点的组合模式叫安全模式,不区分的叫透明模式。

迭代器模式:

      所谓迭代器模式,就是对一个容器中的元素逐个遍历的方法。java在jdk1.5中已经帮我们完美的实现了这个模式。就是我们在java中常用的Iterator接口,我们了解一下这个接口即可。这个接口中有三个方法hasNext,next,remove,在我们使用该接口的时候,可以想象有一开始一个指针指向这个类的第一个元素。然后hasNext就是返回当前指针位置有没有元素,next就是返回当前指针指向的元素,然后把指针移动到下一个位置。remove就是移除掉当前指针指向的元素。然后其他的容器如果想获取被遍历的功能,就要实现该接口,然后实现这三个方法,使用迭代器模式,就可以为各种各样繁琐复杂的容器添加一个共同的遍历接口,在用户遍历某个容器的时候,不用关心这个容器具体是什么东西。这样更利于高层模块的调用。这就是迭代器模式。

转载请注明:王镜鑫的个人博客 » 【原创】设计模式系列(二十一)——组合模式和迭代器模式

喜欢 (4)or分享 (0)

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请狠狠点击下面的

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址