资讯专栏INFORMATION COLUMN

开发之路(设计模式十:迭代器模式上)

Thanatos / 1513人阅读

摘要:感谢你看到这里,迭代器模式上部分到这里就结束了,本人文笔随便,若有不足或错误之处望给予指点,度弯腰很快我会补全这个内容,生命不息,编程不止参考书籍设计模式

有许多种方法可以把对象堆起来成为一个集合

好消息,当地的餐厅和煎饼屋合并了,但是两者实现的方式却不同,这就造成了分歧。让我们一起去看看把。

一个使用ArrayList集合,另一个使用数组实现,事情看起来确实棘手,我们创建一个女招待作为中间人来使用两个菜单的客户代码

这里就有个问题,我们在打印早餐和午餐的时候由于使用对象不同,Arraylist和数组,这样我们就要写两个for循环了,倘若后面还有新的对象加进来做晚餐呢?或许我们能想出一个办法,让他们的菜单实现一个相同的接口,我们是否可以试着封装多个遍历呢?步骤图如下

OK,看来迭代器模式帮助了我们,迭代器(iterator)依赖于迭代器接口。相关类图如下

想要在餐厅菜单中加入迭代器,我们先定义迭代器接口

package MenuItem;

/**
 * 迭代器接口
 * 
 * @author Joy
 * 
 */
public interface Iterator {
    // 知道是否还有更多元素
    boolean hasNext();

    // 返回下一个元素
    Object next();
}

然后先用DinerMenuIterator类去实现接口

package MenuItem;

/**
 * 实现迭代器
 * 
 * @author Joy
 * 
 */
public class DinerMenuIterator implements Iterator {
    MenuItem[] items;
    int position = 0;// 数组索引

    // 构造器初始化传入一个菜单项的数组当参数
    public DinerMenuIterator(MenuItem[] items) {
        this.items = items;
    }

    // 返回数组下一项,索引自+1
    @Override
    public Object next() {
        MenuItem menuItem = items[position];
        position += 1;
        return menuItem;
    }

    // 判断数组是否满了
    @Override
    public boolean hasNext() {
        if (position >= items.length || items[position] == null) {
            return false;
        }
        return true;
    }
}

我们有了菜单迭代器,利用它改写餐厅菜单,DineMenu类中这样写

package MenuItem;

/**
 * 对象村餐厅
 * 
 * @author Joy
 * 
 */
public class DineMenu {
    // 菜单总数
    static final int MAX_ITEMS = 6;
    // 菜单量
    int numberOfItems = 0;
    MenuItem[] menuItems;

    // 初始化数组,添加菜单内容
    public DineMenu() {
        menuItems = new MenuItem[MAX_ITEMS];
        addItem("素食BLT", "(煎)培根、生菜&西红柿并用面包做", true, 2.99);
        addItem("BLT", "培根、生菜&西红柿", false, 2.99);
        addItem("例汤", "一碗例汤、配土豆沙拉", false, 3.29);
        addItem("热狗", "热狗、酸菜、上盖芝士", false, 3.29);
        addItem("清蒸时蔬加糙米", "清蒸的蔬菜配糙米", false, 3.05);

    }

    // 创建一个添加菜单方法
    public void addItem(String name, String description, boolean vegetarian,
            double price) {
        MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
        if (numberOfItems >= MAX_ITEMS) {
            System.out.println("抱歉,菜单已满,不能添加菜单了");
        } else {
            // 菜单还没满还可以继续添加
            menuItems[numberOfItems] = menuItem;
            numberOfItems += 1;
        }
    }

    // 使用迭代器遍历菜单
    public Iterator createIterator() {
        return new DinerMenuIterator(menuItems);
    }
}

完整代码如下

迭代器接口

package MenuItem;

/**
 * 迭代器接口
 * 
 * @author Joy
 * 
 */
public interface Iterator {
    // 知道是否还有更多元素
    boolean hasNext();

    // 返回下一个元素
    Object next();
}

菜单类

package MenuItem;

/**
 * 对象村餐厅
 * 
 * @author Joy
 * 
 */
public class DineMenu {
    // 菜单总数
    static final int MAX_ITEMS = 6;
    // 菜单量
    int numberOfItems = 0;
    MenuItem[] menuItems;

    // 初始化数组,添加菜单内容
    public DineMenu() {
        menuItems = new MenuItem[MAX_ITEMS];
        addItem("素食BLT", "(煎)培根、生菜&西红柿并用面包做", true, 2.99);
        addItem("BLT", "培根、生菜&西红柿", false, 2.99);
        addItem("例汤", "一碗例汤、配土豆沙拉", false, 3.29);
        addItem("热狗", "热狗、酸菜、上盖芝士", false, 3.29);
        addItem("清蒸时蔬加糙米", "清蒸的蔬菜配糙米", false, 3.05);

    }

    // 创建一个添加菜单方法
    public void addItem(String name, String description, boolean vegetarian,
            double price) {
        MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
        if (numberOfItems >= MAX_ITEMS) {
            System.out.println("抱歉,菜单已满,不能添加菜单了");
        } else {
            // 菜单还没满还可以继续添加
            menuItems[numberOfItems] = menuItem;
            numberOfItems += 1;
        }
    }

    // 使用迭代器遍历菜单
    public Iterator createIterator() {
        return new DinerMenuIterator(menuItems);
    }
}

餐厅的实现以及接口

package MenuItem;

/**
 * 实现迭代器
 * 
 * @author Joy
 * 
 */
public class DinerMenuIterator implements Iterator {
    MenuItem[] items;
    int position = 0;// 数组索引

    // 构造器初始化传入一个菜单项的数组当参数
    public DinerMenuIterator(MenuItem[] items) {
        this.items = items;
    }

    // 返回数组下一项,索引自+1
    @Override
    public Object next() {
        MenuItem menuItem = items[position];
        position += 1;
        return menuItem;
    }

    // 判断数组是否满了
    @Override
    public boolean hasNext() {
        if (position >= items.length || items[position] == null) {
            return false;
        }
        return true;
    }
}
package MenuItem;

/**
 * 对象村餐厅
 * 
 * @author Joy
 * 
 */
public class DineMenu {
    // 菜单总数
    static final int MAX_ITEMS = 6;
    // 菜单量
    int numberOfItems = 0;
    MenuItem[] menuItems;

    // 初始化数组,添加菜单内容
    public DineMenu() {
        menuItems = new MenuItem[MAX_ITEMS];
        addItem("素食BLT", "(煎)培根、生菜&西红柿并用面包做", true, 2.99);
        addItem("BLT", "培根、生菜&西红柿", false, 2.99);
        addItem("例汤", "一碗例汤、配土豆沙拉", false, 3.29);
        addItem("热狗", "热狗、酸菜、上盖芝士", false, 3.29);
        addItem("清蒸时蔬加糙米", "清蒸的蔬菜配糙米", false, 3.05);

    }

    // 创建一个添加菜单方法
    public void addItem(String name, String description, boolean vegetarian,
            double price) {
        MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
        if (numberOfItems >= MAX_ITEMS) {
            System.out.println("抱歉,菜单已满,不能添加菜单了");
        } else {
            // 菜单还没满还可以继续添加
            menuItems[numberOfItems] = menuItem;
            numberOfItems += 1;
        }
    }

    // 使用迭代器遍历菜单
    public Iterator createIterator() {
        return new DinerMenuIterator(menuItems);
    }
}

同理煎饼屋的实现和接口

package MenuItem;

import java.util.ArrayList;

public class PancakeHouseIterator implements Iterator {
    ArrayList items;
    int position = 0;

    public PancakeHouseIterator(ArrayList items) {
        this.items = items;
    }

    @Override
    public Object next() {
        Object obj = items.get(position);
        position += 1;
        return obj;
    }

    @Override
    public boolean hasNext() {
        if (position >= items.size()) {
            return false;
        }
        return true;
    }
}
package MenuItem;

import java.util.ArrayList;

/**
 * 对象村煎饼屋菜单
 * 
 * @author Joy
 * 
 */
public class PancakeHouseMenu {
    ArrayList menuItems;

    public PancakeHouseMenu() {
        menuItems = new ArrayList();
        addItem("K&B薄煎饼早餐", "薄煎饼,清蛋和吐司", true, 2.99);
        addItem("薄煎饼早餐例餐", "薄煎饼,煎蛋和香肠", false, 2.99);
        addItem("蓝莓薄煎饼", "新鲜蓝莓和蓝莓糖浆做成的薄煎饼", false, 3.49);
        addItem("松饼", "可以选择蓝莓或草莓", true, 3.59);        

    }

    // 创建一个添加菜单方法
    public void addItem(String name, String description, boolean vegetarian,
            double price) {
        // 菜单项对象,并加入到ArrayList里
        MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
        menuItems.add(menuItem);
    }

    //使用迭代器遍历菜单
    public Iterator createIterator(){
        return new PancakeHouseIterator(menuItems);
    }
}

女招待的实现

package MenuItem;
/**
 * 对象村的女招待
 * 
 * @author Joy
 * 
 */
public class Waitress {
    //创建两个餐厅对象的引用
    PancakeHouseMenu pancakeHouseMenu;
    DineMenu dineMenu;

    // 初始化两个菜单
    public Waitress(PancakeHouseMenu pancakeHouseMenu, DineMenu dineMenu) {
        this.dineMenu = dineMenu;
        this.pancakeHouseMenu = pancakeHouseMenu;
    }

    public void printMenu() {
        // 为每一个菜单创建一个迭代器
        Iterator pancakeitIterator = pancakeHouseMenu.createIterator();
        Iterator dinerIterator = dineMenu.createIterator();
        System.out.println("Menu
=======
BreakFast");
        // 调用下面重载的方法
        printMenus(pancakeitIterator);
        System.out.println("
Lunch");
        // 调用下面重载的方法
        printMenus(dinerIterator);
    }

    // 重载一个printMenu()方法
    // 使用迭代器(一次循环即可)来遍历菜单项并打印出来,只调用Iterator接口
    public void printMenus(Iterator iterator) {
        while (iterator.hasNext()) {
            // 取得下一项
            MenuItem menuItem = (MenuItem) iterator.next();
            System.out.print(menuItem.getName() + ", ");
            System.out.print(menuItem.getPrice() + ", ");
            System.out.println(menuItem.getDescription());
        }
    }
}

测试类

package TestMain;
import MenuItem.DineMenu;
import MenuItem.PancakeHouseMenu;
import MenuItem.Waitress;

public class MenuTestDrive {
    public static void main(String[] args) {
        PancakeHouseMenu pancakeHouseMenu = new PancakeHouseMenu();        
        DineMenu dineMenu = new DineMenu();
        /**
         *两个菜单都实现一样的方法,但是并没有实现相同的接口,
         *女招待还是要依赖两个具体实现的菜单类
         *后面就要修改这里
         *
         */
        Waitress waitress = new Waitress(pancakeHouseMenu, dineMenu);
        waitress.printMenu();
    }
}

效果图如下

很巧妙的将两者迭代取出来了。但两者实现的接口却完全一样,这里其实还可以抽象出来成一个共同接口。

感谢你看到这里,迭代器模式上部分到这里就结束了,本人文笔随便,若有不足或错误之处望给予指点,90度弯腰~~~很快我会补全这个内容,生命不息,编程不止!

参考书籍《Head First设计模式》

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/67657.html

相关文章

  • php设计模式

    摘要:我们今天也来做一个万能遥控器设计模式适配器模式将一个类的接口转换成客户希望的另外一个接口。今天要介绍的仍然是创建型设计模式的一种建造者模式。设计模式的理论知识固然重要,但 计算机程序的思维逻辑 (54) - 剖析 Collections - 设计模式 上节我们提到,类 Collections 中大概有两类功能,第一类是对容器接口对象进行操作,第二类是返回一个容器接口对象,上节我们介绍了...

    Dionysus_go 评论0 收藏0
  • php设计模式

    摘要:我们今天也来做一个万能遥控器设计模式适配器模式将一个类的接口转换成客户希望的另外一个接口。今天要介绍的仍然是创建型设计模式的一种建造者模式。设计模式的理论知识固然重要,但 计算机程序的思维逻辑 (54) - 剖析 Collections - 设计模式 上节我们提到,类 Collections 中大概有两类功能,第一类是对容器接口对象进行操作,第二类是返回一个容器接口对象,上节我们介绍了...

    vspiders 评论0 收藏0
  • JAVA学习之路)集合

    摘要:集合中的集合是一种工具类,就像是容器,存储任意数量的具有共同属性的对象集合的作用在类的内部,对数据进行组织简单而快速的搜索大量数目的条目有的集合接口,提供了一系列排列有序的元素,并且可以在序列中进行快速的插入和删除有些集合接口,提供了映射关 集合 java中的集合: 是一种工具类,就像是容器,存储任意数量的具有共同属性的对象 集合的作用 1. 在类的内部,对数据进行组织 2. 简单而快...

    sutaking 评论0 收藏0

发表评论

0条评论

Thanatos

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<