设计模式——迭代器和组合模式

  想象一个场景,有两个对象(称为聚合对象),一个对象的存储方式是ArrayList,另一个对象存储方式是数组。你是客户端,想遍历这两种数据结构。方案一:分别针对这两种写遍历方法,但是这样代码会变的相当冗余。而方案二:就是迭代器,使用统一的接口来处理不同的集合,并且隐藏了具体的存储方式。就想一个小区里住了很多户人家,要找他们,从前你要到他们家,但是后来小区请了门卫,有门卫来帮你联系。
  另外做为迭代器,首先你要获取数据(构造方法),你至少要有最小的执行单位,一个是next()来获取下一个数据,那随之而来就需要判断下一个是否存在,需要hasNext()方法,再加remove()方法。并且聚合对象要实现迭代器接口,这样客户端就可以针对接口编程,还要需要返回一个迭代器方法,把聚合对象传入进去。

看下定义,迭代器模式:提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。
方法就是next()和hasNext()方法。
这里涉及一个原则,一个类应该只有一个引起变化的原因。

类图

代码

public interface Menu {

    public Iterator createIterator();
}

public class DinerMenu implements Menu{

    static final int MAX_ITEMS = 6;
    int numberOfItems = 0;
    MenuItem[] menuItems;

    public DinerMenu(){
        menuItems = new MenuItem[MAX_ITEMS];
        addItem("Vegetarian BLT","Bacon with lettuce",true,2.99);
        addItem("Soup","Soup of the day",false,2.99);
    }

    public void addItem(String name,String description,
            boolean vegetarian,double price){
        MenuItem menuItem = new MenuItem(name,description,vegetarian,price);
        if(numberOfItems >= MAX_ITEMS){
            System.err.println("sorry");
        }else{
            menuItems[numberOfItems] = menuItem;
            numberOfItems++;
        }
    }

    public Iterator createIterator(){
        return new DinerMenuIterator(menuItems);
    }
}

public class PancakeHouseMenu implements Menu{

    ArrayList menuItems;

    public PancakeHouseMenu(){
        menuItems = new ArrayList();
        addItem("Pancake BLT","Pancakes with egg",true,3.99);
        addItem("Blueberry Pancakes","Blueberry",false,2.59);
    }

    public void addItem(String name,String description,
            boolean vegetarian,double price){
        MenuItem menuItem = new MenuItem(name,description,vegetarian,price);
        menuItems.add(menuItem);
    }

    public Iterator createIterator(){
        return menuItems.iterator();
    }


}

public class MenuItem {

    String name;
    String description;
    boolean vegetarian;
    double price;



    public MenuItem(String name, String description, boolean vegetarian,
            double price) {
        super();
        this.name = name;
        this.description = description;
        this.vegetarian = vegetarian;
        this.price = price;
    }
    public String getName() {
        return name;
    }
    public String getDescription() {
        return description;
    }
    public boolean isVegetarian() {
        return vegetarian;
    }
    public double getPrice() {
        return price;
    }


}

public class Waitress {
    Menu pancakeHouseMenu;
    Menu DinerMenu;

    public Waitress(Menu pancake,Menu diner){
        this.pancakeHouseMenu = pancake;
        this.DinerMenu = diner;
    }

    public void printMenu(){
        Iterator pancakeIterator = pancakeHouseMenu.createIterator();
        Iterator dinerIterator = DinerMenu.createIterator();
        System.out.println("MENU\n----\nBREAKFAST");
        printMenu(pancakeIterator);
        System.out.println("\nLUNCH");
        printMenu(dinerIterator);
    }

    private void printMenu(Iterator iterator){
        while(iterator.hasNext()){
            MenuItem menuItem = (MenuItem)iterator.next();
            System.out.println(menuItem.getName() + ", ");
            System.out.println(menuItem.getPrice() + "--");
            System.out.println(menuItem.getDescription());
        }
    }
}

public class MenuTestDrive {

    public static void main(String[] args) {
        PancakeHouseMenu pancake = new PancakeHouseMenu();
        DinerMenu dinerMenu = new DinerMenu();

        Waitress  waitress = new Waitress(pancake,dinerMenu);
        waitress.printMenu();
    }
}

组合模式
想象一下这样一个场景,餐单,里面有时不仅包含餐点,同时也包含其他餐单,而这餐单里又包含了同样的餐单。这是一种树形结构(组合结构),使用这种结构,我们能把相同的操作应用在组合和个别对象中。
概念,组合对象中,有根(最上层的餐单组件),结点(菜单组件),叶子(菜单项)的概念。
看下定义:组合模式:允许你将对象组合成树形结构来表现”整体/部分”层次结构,组合能让客户以一致的方式处理个别对象以及对象组合。
看类图就明白了
类图

通过叶子和结点同实现共同的接口来实现。在高层抽象类定义所需的方法。
这里的难点是怎么遍历菜单组下面所有的元素。

两种方法:
1.通过递归,共同实现同一个方法,不论是叶子还是结点,通过调用自身来遍历所有。
2.通过实现外部迭代器,通过对迭代器进行操作来代替对链表的直接操作。
代码:
public class CompositeIterator implements Iterator{

    Stack stack = new Stack();

    public CompositeIterator(Iterator iterator){
        stack.push(iterator);
    }

    @Override
    public boolean hasNext() {
        if(stack.empty()){
            return false;
        }else{
            Iterator iterator = (Iterator)stack.peek();
            if(!iterator.hasNext()){
                stack.pop();
                return hasNext();
            }else{
                return true;
            }
        }
    }

    @Override
    public Object next() {
        if(hasNext()){
            Iterator iterator = (Iterator)stack.peek();
            MenuComponent component = (MenuComponent)iterator.next();
            if(component instanceof Menu){
                stack.push(component.createIterator());
            }
            return component;
        }else{
        return null;
        }
    }

    @Override
    public void remove() {
        throw new UnsupportedOperationException();
    }


}

例子代码

最顶层抽象类
public abstract class MenuComponent {

    public void add(MenuComponent Component){
        throw new UnsupportedOperationException();
    }

    public void remove(MenuComponent Component){
        throw new UnsupportedOperationException();
    }

    public String getName(){
        throw new UnsupportedOperationException();
    }

    public String getDescription(){
        throw new UnsupportedOperationException();
    }

    public double getPrice(){
        throw new UnsupportedOperationException();
    }

    public boolean isVegetarian(){
        throw new UnsupportedOperationException();
    }

    public void print(){
        throw new UnsupportedOperationException();
    }

    public Iterator createIterator(){
        throw new UnsupportedOperationException();
    }
}


菜单组(结点)
public class Menu extends MenuComponent{

    ArrayList menuComponents = new ArrayList();
    String name;
    String description;

    public Menu(String name,String description){
        this.name = name;
        this.description = description;
    }

    public void add(MenuComponent Component){
        menuComponents.add(Component);
    }

    public void remove(MenuComponent Component){
        menuComponents.remove(Component);
    }

    public String getName(){
        return name;
    }

    public String getDescription(){
        return description;
    }

    public void print(){
        System.out.print("\n" + getName());
        System.out.print(", " + getDescription());
        System.out.println("----------------");

        Iterator iterator = menuComponents.iterator();
        while(iterator.hasNext()){
            MenuComponent menuComponent = 
                    (MenuComponent)iterator.next();
            menuComponent.print();
        }
    }

    public Iterator createIterator(){
        return new CompositeIterator(menuComponents.iterator());
    }
}

叶子
public class MenuItem extends MenuComponent{

    String name;
    String description;
    boolean vegetarian;
    double price;



    public MenuItem(String name, String description, boolean vegetarian,
            double price) {
        super();
        this.name = name;
        this.description = description;
        this.vegetarian = vegetarian;
        this.price = price;
    }
    public String getName() {
        return name;
    }
    public String getDescription() {
        return description;
    }
    public boolean isVegetarian() {
        return vegetarian;
    }
    public double getPrice() {
        return price;
    }

    public void print(){
        System.out.println(" " + getName());
        if(isVegetarian()){
            System.out.println("(v)");
        }
        System.out.println(", " + getPrice());
        System.out.println(" --" + getDescription());
    }


}



客户端
public class Waitress {

    MenuComponent allMenus;

    public Waitress(MenuComponent allMenus){
        this.allMenus = allMenus;
    }

    public void printMenu(){
        allMenus.print();
    }

    public void printVegetariarianMenu(){
        Iterator iterator = allMenus.createIterator();
        System.out.println("\nVEGETARIAN MENU\n----");
        while(iterator.hasNext()){
            MenuComponent menuComponent = 
                    (MenuComponent)iterator.next();
            try {
                if(menuComponent.isVegetarian()){
                    menuComponent.print();
                }
            } catch (Exception e) {
                // TODO: handle exception
            }
        }
    }
}

public class MenuTestDrive {

    public static void main(String args[]){
        MenuComponent pancakeHouseMenu = 
                new Menu("PANCAKE House","Breakfast");
        MenuComponent dinerMenu = 
                new Menu("DINER MENU","Lunch");
        MenuComponent dessertMenu = 
                new Menu("DESSERT MENU","DESSERT of course");

        MenuComponent allMenus = new Menu("All menus","All menus");
        allMenus.add(pancakeHouseMenu);
        allMenus.add(dinerMenu);
        allMenus.add(dessertMenu);

        dinerMenu.add(new MenuItem("Pasta","Spaghetti",true,3.89));
        dinerMenu.add(dessertMenu);
        dessertMenu.add(new MenuItem("Apple Pie","Apple",true,1.59));

        Waitress waitress = new Waitress(allMenus);
        waitress.printMenu();
        System.out.println("----------------------------------");
        waitress.printVegetariarianMenu();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值