美文网首页
组合模式

组合模式

作者: yangzai | 来源:发表于2018-01-17 23:46 被阅读6次
    • 定义:
      将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。
    • UML:


      image.png
    • 模型:
      餐厅点餐软件上的,菜单->子菜单->菜单项,菜单下可能有子菜单或者菜单项,子菜单下也可能有子菜单或菜单项,类似树形结构


      image.png
    //抽象出统一的菜单组件(这个是统一对外暴露的数据结构)
    public abstract class MenuComponent {
        public String getName() {
            return "";
        }
        public String getDescription() {
            return "";
        }
        public float getPrice() {
            return 0;
        }
        public boolean isVegetable() {
            return false;
        }
        public abstract void print();
        public Iterator getIterator() {
            return new NullIterator();
        }
    }
    //具体的一个菜单项
    public class MenuItem extends MenuComponent{
        private String name,description;
        private boolean vegetable;
        private float price;
        public MenuItem(String name,String description,boolean vegetable,float price){
            this.name=name;
            this.description=description;
            this.vegetable=vegetable;
            this.price=price;
        }
        @Override
        public String getName(){
            return name;
        }
        @Override
        public String getDescription(){
            return description;
        }
        @Override
        public float getPrice(){
            return price;
        }
        @Override
        public boolean  isVegetable(){
            return vegetable;
        }
        @Override
        public void print() {
            System.out.println(getName() + "***" + getPrice() + "***"
                    + getDescription());
        }
    }
    //菜单
    public class DinerMenu extends MenuComponent {
        private final static int Max_Items = 5;
        private int numberOfItems = 0;
            //数组方式记录子菜单项
        private MenuComponent[] menuItems;
        public DinerMenu() {
            menuItems = new MenuComponent[Max_Items];
            addItem("vegetable Blt", "bacon&lettuce&tomato&cabbage", true, 3.58f);
            addItem("Blt", "bacon&lettuce&tomato", false, 3.00f);
            addItem("bean soup", "bean&potato salad", true, 3.28f);
            addItem("hotdog", "onions&cheese&bread", false, 3.05f);
            addSubMenu(new SubMenu());
        }
        private void addItem(String name, String description, boolean vegetable,
                float price) {
            MenuItem menuItem = new MenuItem(name, description, vegetable, price);
            if (numberOfItems >= Max_Items) {
                System.err.println("sorry,menu is full!can not add another item");
            } else {
                menuItems[numberOfItems] = menuItem;
                numberOfItems++;
            }
        }
           //子菜单再添加子菜单(子菜单特有的方法)
        private void addSubMenu(MenuComponent mMenuComponent){
            if (numberOfItems >= Max_Items) {
                System.err.println("sorry,menu is full!can not add another item");
            } else {
                menuItems[numberOfItems] = mMenuComponent;
                numberOfItems++;
            }
        }
            //这里返回的是一个包装迭代器,
        public Iterator getIterator() {
            return new ComposeIterator(new DinerIterator());
        }
            //自己的迭代器
        class DinerIterator implements Iterator {
            private int position;
            public DinerIterator() {
                position = 0;
            }
            @Override
            public boolean hasNext() {
                if (position < numberOfItems) {
                    return true;
                }
                return false;
            }
            @Override
            public Object next() {
                MenuComponent menuItem = menuItems[position];
                position++;
                return menuItem;
            }
            @Override
            public void remove() {}
        }
        @Override
        public void print() {
            System.out.println("****This is DinerMenu****");
        };
    }
    //装饰迭代器(操作时先调用被装饰者方法)
    public class ComposeIterator implements Iterator {
        private Stack<Iterator> stack = new Stack<Iterator>();
        public ComposeIterator(Iterator iterator) {
            stack.push(iterator);
        }
        @Override
        public boolean hasNext() {
            // TODO Auto-generated method stub
            if (stack.empty()) {
                return false;
            }
            Iterator iterator = stack.peek();
            if (!iterator.hasNext()) {
                stack.pop();
                return hasNext();
            } else {
                return true;
            }
        }
        @Override
        public Object next() {
            if (hasNext()) {
                Iterator iterator = stack.peek();
                MenuComponent mMenuComponent = (MenuComponent) iterator.next();
                stack.push(mMenuComponent.getIterator());
                return mMenuComponent;
            }
            return null;
        }
        @Override
        public void remove() {}
    }
    
    //子菜单
    public class SubMenu extends MenuComponent {
        private ArrayList<MenuComponent> menuItems;
        public SubMenu() {
            menuItems = new ArrayList<MenuComponent>();
            addItem("Apple Cookie", "Apple&candy&Cookie", true, 1.99f);
            addItem("Banana Cookie", "Banana&candy&Cookie", false, 1.59f);
            addItem("Orange Cookie", "Orange&Cookie", true, 1.29f);
        }
        private void addItem(String name, String description, boolean vegetable,
                float price) {
            MenuItem menuItem = new MenuItem(name, description, vegetable, price);
            menuItems.add(menuItem);
        }
        public Iterator getIterator() {
            return new ComposeIterator(menuItems.iterator());
        }
        @Override
        public void print() {
            System.out.println("****This is SubMenu****");
        };
        // 其他功能代码
    }
    //缺省适配
    public class NullIterator implements Iterator{
        @Override
        public boolean hasNext() {
            return false;
        }
        @Override
        public Object next() {
            return null;
        }
        @Override
        public void remove() {}
    }
    //没有子菜单的菜单
    public class CakeHouseMenu extends MenuComponent {
          //集合形式存储菜单项
        private ArrayList<MenuComponent> menuItems;
        public CakeHouseMenu() {
            menuItems = new ArrayList<MenuComponent>();
            addItem("KFC Cake Breakfast", "boiled eggs&toast&cabbage", true, 3.99f);
            addItem("MDL Cake Breakfast", "fried eggs&toast", false, 3.59f);
            addItem("Stawberry Cake", "fresh stawberry", true, 3.29f);
            addItem("Regular Cake Breakfast", "toast&sausage", true, 2.59f);
        }
        private void addItem(String name, String description, boolean vegetable,
                float price) {
            MenuItem menuItem = new MenuItem(name, description, vegetable, price);
            menuItems.add(menuItem);
        }
        public Iterator getIterator() {
            return new ComposeIterator(menuItems.iterator());
        }
        @Override
        public void print() {
            System.out.println("****This is CakeHouseMenu****");
        };
        // 其他功能代码
    }
    
    • 使用组合模式:
    public class Waitress {
        private ArrayList<MenuComponent> iterators = new ArrayList<MenuComponent>();
        public Waitress() {}
        public void addComponent(MenuComponent mMenuComponent) {
            iterators.add(mMenuComponent);
        }
        public void printMenu() {
            Iterator iterator;
            MenuComponent menuItem;
                    //遍历时并不关心菜单或子菜单项的数据结构,只要调用其暴露出来的接口Iterator。
            for (int i = 0, len = iterators.size(); i < len; i++) {
                iterators.get(i).print();
                iterator = iterators.get(i).getIterator();
                while (iterator.hasNext()) {
                    menuItem = (MenuComponent) iterator.next();
                    menuItem.print();
                }
            }
        }
    }
    
    • 测试:
    public class MainTest {
        public static void main(String[] args) {
            Waitress mWaitress = new Waitress();
            CakeHouseMenu mCakeHouseMenu = new CakeHouseMenu();
            DinerMenu mDinerMenu = new DinerMenu();
            mWaitress.addComponent(mCakeHouseMenu);
            mWaitress.addComponent(mDinerMenu);
            mWaitress.printMenu();
        }
    }
    
    • 通过使用组合模式,我们将菜单与子菜单抽象成菜单组件。对使用者来说是透明的,操作具有一致性,忽略整体与部分的差异。
      子菜单可以看成存储菜单组件的容器,这样我们就可以组合出很多层次,形成复杂的树形结构。

    相关文章

      网友评论

          本文标题:组合模式

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