美文网首页
访问者模式

访问者模式

作者: 阳光的技术小栈 | 来源:发表于2018-01-22 15:14 被阅读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. 
    

    相关文章

      网友评论

          本文标题:访问者模式

          本文链接:https://www.haomeiwen.com/subject/fvqqaxtx.html