设计模式之----迭代器模式

设计模式之迭代器模式

  • 迭代器模式总结
  • 两个餐馆合并案例
  • 传统设计
  • 迭代器模式设计
  • Java内置迭代器设计
  • 单一责任原则

迭代器模式总结

  • 迭代器模式(Iterator Pattern)是 Java 和 .Net 编程环境中非常常用的设计模式。这种模式用于顺序访问集合对象的元素,不需要知道集合对象的底层表示。
  • 提供一种方法顺序访问一个聚合对象中各个元素, 而又无须暴露该对象的内部表示。把在元素之间游走的责任交给迭代器,而不是聚合对象。
  • 优点: 1、它支持以不同的方式遍历一个聚合对象。 2、迭代器简化了聚合类。 3、在同一个聚合上可以有多个遍历。 4、在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码。
  • 迭代器模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可让外部代码透明地访问集合内部的数据。

两个餐馆合并案例

案例:
现在有两个餐馆,一个蛋糕店,一个中餐厅,都有各自的菜单,现在要合并,也就是说要通过一个女服务员直接点单:
这里写图片描述


传统设计

这里写图片描述

首先两个餐厅:

package iterator.bad;

import java.util.ArrayList;

/**
 * 蛋糕店
 */
public class CakeHouse {

    private ArrayList<MenuItem> menuItems;

    public CakeHouse() {
        menuItems = new ArrayList<>();
        addItem("Cakefood1",33.3);
        addItem("Cakefood2",44.4);
    }

    private void addItem(String name,double price){
        MenuItem menuItem = new MenuItem(name,price);
        menuItems.add(menuItem);
    }

    //获取菜单项 //暴露在外面 //耦合度高,  封装性不好
    public ArrayList<MenuItem> getMenuItems() {
        return menuItems;
    }
}
package iterator.bad;


/**
 * 中餐厅
 */
public class DinerHouse {

    private final static int Max_Item = 5;//最多只有五个菜单项

    private int cur; //游标  

    public int getCur() {
        return cur;
    }

    private MenuItem[] menuItems;

    public DinerHouse() {
        menuItems = new MenuItem[Max_Item];
        addItem("Dinerfood1",11.1);
        addItem("Dinerfood2",22.2);
    }

    public void addItem(String name,double price){
        MenuItem menuItem = new MenuItem(name,price);
        if(cur >= Max_Item){
            System.out.println("sorry! menu is full! can't add any item!");
        }else {
            menuItems[cur++] = menuItem;
        }
    }
    //暴露出来
    public MenuItem[] getMenuItems() {
        return menuItems;
    }
}

菜单项:

package iterator.bad;

/**
 * 每个餐厅的菜单项
 */
public class MenuItem {

    private String name;
    private double price;


    public MenuItem(String name, double price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public double getPrice() {
        return price;
    }
}

女招待:

package iterator.bad;

import java.util.ArrayList;

/**
 * 女招待员
 * 必须同时有两个对象的引用
 */
public class Waitress {

    //蛋糕店的
    private CakeHouse cakeHouse;
    private ArrayList<MenuItem> cakeItems;

    //中餐厅的
    private DinerHouse dinerHouse;
    private MenuItem[] dinerItems;


    public Waitress() {
        cakeHouse = new CakeHouse();
        cakeItems = cakeHouse.getMenuItems();

        dinerHouse = new DinerHouse();
        dinerItems = dinerHouse.getMenuItems();
    }

    public void printMenu(){
        MenuItem item = null;
        for(int i = 0; i < cakeItems.size(); i++){
            item = cakeItems.get(i);
            System.out.println(item.getName() + " " + item.getPrice());
        }
        for(int i = 0; i < dinerHouse.getCur(); i++){
            item = dinerItems[i];
            System.out.println(item.getName() + " " + item.getPrice());
        }
    }

}

测试:

package iterator.bad;

public class MyTest {

    public static void main(String[] args) {
        Waitress waitress = new Waitress();
        waitress.printMenu();
    }
}

输出:

Cakefood1 33.3
Cakefood2 44.4
Dinerfood1 11.1
Dinerfood2 22.2

这中方案存在的问题:

  • 如果再来一个餐厅要合并,比如说菜单是HashTable的,这样那边也要暴露自己的菜单,而且女招待要修改代码;
  • 开发要针对接口的开发,而不是具体实现的开发,而且这样设计耦合性增加;

迭代器模式设计

这里写图片描述
这里写图片描述
先看迭代器:

package iterator.good;

/**
 * 迭代器的接口
 */
public interface Iterator {
    public boolean hasNext();
    public Object next();
}

两个餐厅:

package iterator.good;

import java.util.ArrayList;

/**
 * 蛋糕店
 */
public class CakeHouse {

    private ArrayList<MenuItem> menuItems;

    public CakeHouse() {
        menuItems = new ArrayList<>();
        addItem("Cakefood1",33.3);
        addItem("Cakefood2",44.4);
    }

    private void addItem(String name,double price){
        MenuItem menuItem = new MenuItem(name,price);
        menuItems.add(menuItem);
    }


    //实现迭代器的设计  不能设计为静态的
    private class CakeHouseIterator implements Iterator{

        private int pos;

        public CakeHouseIterator() {
            pos = 0;
        }

        @Override
        public boolean hasNext() {
            if(pos < menuItems.size()){
                return true;
            }
            return false;
        }

        @Override
        public Object next() {
            MenuItem menuItem = menuItems.get(pos++);
            return menuItem;
        }
    }

    public Iterator getIterator(){
       return new CakeHouseIterator();
    }
}
package iterator.good;

/**
 * 中餐厅
 */
public class DinerHouse {

    private final static int Max_Item = 5;//最多只有五个菜单项

    private int cur; //游标  

    private MenuItem[] menuItems;

    public DinerHouse() {
        menuItems = new MenuItem[Max_Item];
        addItem("Dinerfood1",11.1);
        addItem("Dinerfood2",22.2);
    }

    public void addItem(String name,double price){
        MenuItem menuItem = new MenuItem(name,price);
        if(cur >= Max_Item){
            System.out.println("sorry! menu is full! can't add any item!");
        }else {
            menuItems[cur++] = menuItem;
        }
    }

    private class DinerHouseIterator implements Iterator{
        private int pos;

        public DinerHouseIterator() {
            pos = 0;
        }

        @Override
        public boolean hasNext() {
            if(pos < cur){
                return true;
            }
            return false;
        }

        @Override
        public Object next() {
            MenuItem menuItem = menuItems[pos++];
            return menuItem;
        }
    }

    public Iterator getIterator(){
        return new DinerHouseIterator();
    }
}

菜单项(不变的):

package iterator.good;

/**
 * 每个餐厅的菜单项
 */
public class MenuItem {

    private String name;
    private double price;


    public MenuItem(String name, double price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public double getPrice() {
        return price;
    }
}

女招待:

package iterator.good;

import iterator.good.MenuItem;

import java.util.ArrayList;

/**
 * 女招待  直接遍历Iterator
 */
public class Waitress {

    private ArrayList<Iterator> iterators = new ArrayList<>();

    public Waitress() {
    }

    //放入迭代器
    public void addIterator(Iterator iterator){
        iterators.add(iterator);
    }

    //不需要知道有些什么餐厅  完全解耦
    public void printMenu(){
        Iterator iterator = null;
        MenuItem menuItem = null;

        for(int i = 0; i < iterators.size(); i++){
            iterator = iterators.get(i); //每一个集合容器
            while(iterator.hasNext()){
                menuItem = (MenuItem)iterator.next();
                System.out.println(menuItem.getName() + " " + menuItem.getPrice());
            }
        }

    }
}

测试类:

package iterator.good;

public class MyTest {
    public static void main(String[] args) {

        CakeHouse cake = new CakeHouse();
        DinerHouse diner = new DinerHouse();

        Waitress waitress = new Waitress();

        waitress.addIterator(cake.getIterator());
        waitress.addIterator(diner.getIterator());

        waitress.printMenu();

    }
}

输出效果(和之前的一样):

Cakefood1 33.3
Cakefood2 44.4
Dinerfood1 11.1
Dinerfood2 22.2

使用迭代器设计模式很好的满足了扩容性和解耦。


Java内置迭代器设计

这里写图片描述
这里写图片描述
三家餐厅: (其中只有中餐厅使用的是数组,所以还是自己要添加一个,并实现Java中的Iterator接口)

package iterator.java;

import java.util.ArrayList;
import java.util.Iterator;

/**
 * 蛋糕店
 */
public class CakeHouse {

    private ArrayList<MenuItem> menuItems;  //因为arrayList在java内部已经是实现了Iterator接口,所以可以直接得到

    public CakeHouse() {
        menuItems = new ArrayList<>();
        addItem("Cakefood1",33.3);
        addItem("Cakefood2",44.4);
    }

    private void addItem(String name,double price){
        MenuItem menuItem = new MenuItem(name,price);
        menuItems.add(menuItem);
    }

    public Iterator getIterator(){
        return menuItems.iterator();  //内部的
    }
}
package iterator.java;


import java.util.Iterator;

/**
 * 中餐厅
 */
public class DinerHouse {

    private final static int Max_Item = 5;//最多只有五个菜单项

    private int cur; //游标   注意这里设置成public 的是为了要Waitress中使用

    private MenuItem[] menuItems;

    public DinerHouse() {
        menuItems = new MenuItem[Max_Item];
        addItem("Dinerfood1",11.1);
        addItem("Dinerfood2",22.2);
    }

    public void addItem(String name,double price){
        MenuItem menuItem = new MenuItem(name,price);
        if(cur >= Max_Item){
            System.out.println("sorry! menu is full! can't add any item!");
        }else {
            menuItems[cur++] = menuItem;
        }
    }

    /**
     * 实现的是  Java内置的util包里面的
     */
    private class DinerHouseIterator implements Iterator {
        private int pos;

        public DinerHouseIterator() {
            pos = 0;
        }

        @Override
        public boolean hasNext() {
            if(pos < cur){
                return true;
            }
            return false;
        }

        @Override
        public Object next() {
            MenuItem menuItem = menuItems[pos++];
            return menuItem;
        }

        @Override
        public void remove() {

        }
    }

    public Iterator getIterator(){
        return new DinerHouseIterator();
    }
}

新加的咖啡馆: (使用HashTable):

package iterator.java;

import java.util.Hashtable;
import java.util.Iterator;

/**
 * 新增的咖啡餐厅
 */
public class CafeHouse {

    private Hashtable<String,MenuItem> menuItems;

    public CafeHouse() {
        menuItems = new Hashtable<>();
        addItem("Cafefood1",55.5);
        addItem("Cafefood2",66.6);
    }

    public void addItem(String name,double price){
        MenuItem menuItem = new MenuItem(name,price);
        menuItems.put(name,menuItem);
    }

    public Iterator getIterator(){
        return menuItems.values().iterator(); //都有一个聚类 包括keys()和values()
    }
}

菜单项和女服务完全不需要改动:

package iterator.java;

/**
 * 每个餐厅的菜单项
 */
public class MenuItem {

    private String name;
    private double price;


    public MenuItem(String name, double price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public double getPrice() {
        return price;
    }
}
package iterator.java;

import java.util.ArrayList;
import java.util.Iterator;

/**
 * 女招待  直接遍历Iterator
 */
public class Waitress {

    private ArrayList<Iterator> iterators = new ArrayList<>();

    public Waitress() {
    }

    //放入迭代器
    public void addIterator(Iterator iterator){
        iterators.add(iterator);
    }

    //不需要知道有些什么餐厅  完全解耦
    public void printMenu(){
        Iterator iterator = null;
        MenuItem menuItem = null;

        for(int i = 0; i < iterators.size(); i++){
            iterator = iterators.get(i); //每一个集合容器
            while(iterator.hasNext()){
                menuItem = (MenuItem)iterator.next();
                System.out.println(menuItem.getName() + " " + menuItem.getPrice());
            }
        }

    }
}

测试:

package iterator.java;

public class MyTest {
    public static void main(String[] args) {

        CakeHouse cake = new CakeHouse();
        DinerHouse diner = new DinerHouse();
        CafeHouse cafe = new CafeHouse();

        Waitress waitress = new Waitress();

        waitress.addIterator(cake.getIterator());
        waitress.addIterator(diner.getIterator());
        waitress.addIterator(cafe.getIterator());

        waitress.printMenu();

    }
}

效果:

这里写图片描述
注意这里的Hash表输出和添加的顺序无关
再次体会到这样设计的好处:

  • 不需要修改女招待的代码;
  • 解耦和封装;

单一责任原则

概念: 一个类应该只有一个引起变化的原因。

  • 一个类只解决一个问题或者一个变化,比如说菜单项这个类,只是用来存储菜单的,至于遍历以及其他,由其他类完成;
  • 就是尽量不要一个类牵扯太多东西,目的还是为了降低耦合性;

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值