访问者模式

2018-01-22  本文已影响15人  阳光的技术小栈

当你想要为一个对象的组合增加新的能力,且封装并不重要时,就使用访问者模式。

示例—营养成分

餐厅的菜单中除了显示除了显示菜单、菜单项以及原料外,客户要求每当顾客询问营养信息时,在不破坏原结构的情况下,需要把具体某项的营养信息显示出来。还要保证以后扩展起来比较方便,不用每次扩展都添加许多新方法。

UML图表示

访问者模式-营养成分

代码演示

菜单抽象类

package Visitor;

import java.util.Iterator;

public abstract class MenuComponent {

    private String name;

    public MenuComponent(String name){
        this.name = name;
    }

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

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

    public MenuComponent getChild(int i){
        throw new UnsupportedOperationException();
    }

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

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

    public void getState(Visitor visitor){
        visitor.getHealthRating(this);
        visitor.getCalories(this);
        visitor.getProtein(this);
        visitor.getCarbs(this);
    }

    public abstract MenuComponent getMenu(String name);

    public String getName(){
        return name;
    }

}

菜单项类

package Visitor;

import java.util.Iterator;

public class MenuItem extends MenuComponent {

    public MenuItem(String name){
        super(name);
    }

    @Override
    public String toString() {
        return getName();
    }

    @Override
    public void print() {
        System.out.print(" " + getName());
    }

    @Override
    public Iterator createIterator() {
        return new NullIterator();
    }

    @Override
    public MenuComponent getMenu(String name) {
        if (name == getName()) return this;
        return null;
    }
}

菜单类

package Visitor;


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

public class Menu extends MenuComponent {

    ArrayList menuComponents = new ArrayList();

    public Menu(String name){
        super(name);
    }

    @Override
    public void add(MenuComponent menuComponent){
        menuComponents.add(menuComponent);
    }

    @Override
    public void remove(MenuComponent menuComponent){
        menuComponents.remove(menuComponent);
    }

    @Override
    public MenuComponent getChild(int i) {
        return (MenuComponent)menuComponents.get(i);
    }

    @Override
    public void print() {
        System.out.print("\n" + getName());
        System.out.print(": ");

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

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

    @Override
    public MenuComponent getMenu(String name) {

        Iterator<MenuComponent> iterator = menuComponents.iterator();

        if (name == getName()) return this;

        while (iterator.hasNext()){
            MenuComponent menuComponent =  iterator.next();
            MenuComponent menu = menuComponent.getMenu(name);
            if (menu != null){
                return menu;
            }
        }
        return null;
    }

}

自定义迭代器

package Visitor;

import TreeMenu.Menu;
import TreeMenu.MenuComponent;

import java.util.Iterator;
import java.util.Stack;

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();
    }
}

空迭代器

package Visitor;

import java.util.Iterator;

public class NullIterator implements Iterator {
    @Override
    public boolean hasNext() {
        return false;
    }

    @Override
    public Object next() {
        return null;
    }

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

访问类

package Visitor;

import java.util.Random;

public class Visitor {

    Random random = new Random(47);

    public void getHealthRating(MenuComponent menuComponent) {
        System.out.println("HealthRating of " + menuComponent.getName() +  " is " + random.nextInt(10) + ". ");
    }

    public void getCalories(MenuComponent menuComponent) {
        System.out.println("Calories of " + menuComponent.getName() +  " is " + random.nextInt(2000)  + ". ");
    }

    public void getProtein(MenuComponent menuComponent) {
        System.out.println("Protein of " + menuComponent.getName() +  " is " + random.nextInt(100)  + ". ");
    }

    public void getCarbs(MenuComponent menuComponent) {
        System.out.println("Carbs of " + menuComponent.getName() +  " is " + random.nextInt(200)  + ". ");
    }

}

服务员类

package Visitor;

public class Waitress {
    MenuComponent allMenus;

    Visitor visitor;

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

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

    public void showNutrient(String name){
        if (allMenus != null){
            MenuComponent menuComponent = allMenus.getMenu(name);
            if (menuComponent != null){
                menuComponent.getState(visitor);
            }
        }
    }

}

测试代码

package Visitor;

public class VisitorDriver {
    public static void main(String[] args) {
        MenuComponent pancakeHouseMenu = new Menu("PANCAKE HOUSE MENU");
        MenuComponent dinerMenu = new Menu("DINER MENU");
        MenuComponent allMenus = new Menu("All MENUS");
        allMenus.add(pancakeHouseMenu);
        allMenus.add(dinerMenu);

        MenuComponent d1 = new Menu("Vegetarian BLT");
        MenuComponent d11 = new MenuItem("Bacon");
        MenuComponent d12 = new MenuItem("Lettuce");
        MenuComponent d13 = new MenuItem("Tomato");
        MenuComponent d14 = new MenuItem("Wheat");

        d1.add(d11);
        d1.add(d12);
        d1.add(d13);
        d1.add(d14);

        MenuComponent d2 = new Menu("Soup of the day");
        MenuComponent d21 = new MenuItem("Tomato");
        MenuComponent d22 = new MenuItem("Potato");

        d2.add(d21);
        d2.add(d22);

        dinerMenu.add(d1);
        dinerMenu.add(d2);

        MenuComponent p1 = new Menu("K&B's Pancake Breakfast");
        MenuComponent p11 = new MenuItem("Pancakes");
        MenuComponent p12 = new MenuItem("Eggs");
        MenuComponent p13 = new MenuItem("Toast");

        p1.add(p11);
        p1.add(p12);
        p1.add(p13);


        MenuComponent p2 = new Menu("Waffles");
        MenuComponent p21 = new MenuItem("Waffles");
        MenuComponent p22 = new MenuItem("Blueberries");

        p2.add(p21);
        p2.add(p22);

        pancakeHouseMenu.add(p1);
        pancakeHouseMenu.add(p2);

        Waitress waitress = new Waitress(allMenus);
        waitress.printMenu();
        System.out.println();
        System.out.println("-------------------------");
        waitress.showNutrient("Vegetarian BLT");
        System.out.println("-------------------------");
        waitress.showNutrient("Blueberries");

    }
}

测试结果

All MENUS: 
PANCAKE HOUSE MENU: 
K&B's Pancake Breakfast:  Pancakes Eggs Toast
Waffles:  Waffles Blueberries
DINER MENU: 
Vegetarian BLT:  Bacon Lettuce Tomato Wheat
Soup of the day:  Tomato Potato
-------------------------
HealthRating of Vegetarian BLT is 8. 
Calories of Vegetarian BLT is 555. 
Protein of Vegetarian BLT is 93. 
Carbs of Vegetarian BLT is 61. 
-------------------------
HealthRating of Blueberries is 1. 
Calories of Blueberries is 429. 
Protein of Blueberries is 68. 
Carbs of Blueberries is 0. 
上一篇下一篇

猜你喜欢

热点阅读