深入浅出设计模式-011:组合模式(Composite Pattern)

本文通过餐厅菜单实例,深入探讨了组合模式的设计理念与实现方法。展示了如何利用组合模式简化多层级对象管理,使得客户端代码能够一致地处理单个对象或对象组合。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

深入浅出设计模式-011:组合模式(Composite Pattern)

一:针对迭代器模式,当添加新菜单时不方便
    class Waitress{
        Menu pancakeHouseMenu;
        Menu dinnerMenu;

        public Waitress(Menu pancakeHouseMenu, Menu dinnerMenu){
            this.pancakeHouseMenu = pancakeHouseMenu;
            this.dinnerMenu = dinnerMenu;
        }

        public string PrintMenu(){
            StringBuilder sb = new StringBuilder();

            Iterator pancakeIterator = pancakeHouseMenu.createIterator();
            Iterator dinnerIterator = dinnerMenu.createIterator();

            //不符合接口封闭原则
            sb.Append("MENU/n----/nBREAKFAST/n");
            sb.Append(PrintMenu(pancakeIterator));
            sb.Append("/nLUNCH/n");
            sb.Append(PrintMenu(dinnerIterator));

            return sb.ToString();
        }

        public string PrintMenu(Iterator iterator){
            StringBuilder sb = new StringBuilder();
            while (iterator.hasNext()){
                MenuItem menuItem = (MenuItem)iterator.next();

                sb.Append(menuItem.getName + ", ");
                sb.Append(menuItem.getPrice + " -- ");
                sb.Append(menuItem.getDescription + "/n");
            }
            return sb.ToString();
        }
    }

    static void Main(string[] args){
        PancakeHouseMenu pancakeHouseMenu = new PancakeHouseMenu();
        DinerMenu dinerMenu = new DinerMenu();
        CafeMenu cafeMenu = new CafeMenu();

        Waitress waitress = new Waitress(pancakeHouseMenu, dinerMenu, cafeMenu);
        Console.WriteLine(waitress.PrintMenu());
    }

二:组合模式:允许你将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象及对象组合。
    为了保持透明性,组合内所有的对象必须实现相同的接口,否则客户就必须操心哪个对象调用哪个接口,这就失去了组合模式的意图。这也意味着有些对象具备一些没有意义的方法调用。
    //菜单项不用分什么,作为统一的叶子节点
    //需要维护菜单列表,列表项及菜单项

    //将菜单和菜的选项全部放进来
    public abstract class MenuComponent{
  string name;
  string description;
  bool vegetarian;
  double price;
  public virtual string Name{
   get {return name;}
   set {name = value;}
  }
  public virtual string Description{
   get { return description; }
   set { description = value; }
  }
  public virtual bool IsVegetarian{
   get { return vegetarian; }
   set { vegetarian = value; }
  }
  public virtual double Price{
   get { return price; }
   set { price = value; }
  }
  public virtual void Add(MenuComponent menuComponent){
   throw new UnsupportedOperationException();
  }
  public virtual void Remove(MenuComponent menuComponent){
   throw new UnsupportedOperationException();
  }
  public virtual MenuComponent GetChild(int i) {
   throw new UnsupportedOperationException();
  }
  public virtual string Print(){
   throw new UnsupportedOperationException();
  }
  public virtual ArrayList GetMenu(){
   throw new UnsupportedOperationException();
  }
  public virtual int Count(){
   throw new UnsupportedOperationException();
  }
 }

 public class MenuItem : MenuComponent{
  string name;
  string description;
  bool vegetarian;
  double price;

  public MenuItem(string name, string description, bool vegetarian, double price){
   this.name = name;
   this.description = description;
   this.vegetarian = vegetarian;
   this.price = price;
  }
  public override string Name{
   get {return name;}
   set {this.name = value;}
  }
  public override string Description{
   get{return description;}
   set{this.description = value;}
  }
  public override double Price{
   get{return price;}
   set{price = value;}
  }
  public override bool IsVegetarian{
   get{return vegetarian;}
   set{this.vegetarian = value;}
  }
  public override string Print(){
   StringBuilder printOutPut = new StringBuilder();
   printOutPut.Append("/t" + Name);
   if(IsVegetarian){
    printOutPut.Append(" (v) ");
   }
   printOutPut.Append(", $" + Price + "/n");
   printOutPut.Append("/t/t--" + Description +"/n");

   return printOutPut.ToString();
  }
 }

 public class Menu : MenuComponent{
        //关键
  ArrayList menuComponents = new ArrayList();
  string name;
  string description;

  public Menu(string name, string description){
   this.name = name;
   this.description = description;
  }
  public override string Name{
   get {return name;}
   set {this.name = value;}
  }
  public override string Description{
   get{return description;}
   set{this.description = value;}
  }
        //菜单中可以增加菜单项,但也可以增加菜单,所以要同一个父节点
  public override void Add(MenuComponent menuComponent){
   menuComponents.Add(menuComponent);
  }
  public override void Remove(MenuComponent menuComponent){
   menuComponents.Remove(menuComponent);
  }
  public override MenuComponent GetChild(int i){
   return (MenuComponent)menuComponents[i];
  }
  public override ArrayList GetMenu(){
   return menuComponents;
  }
  public override int Count(){
   return menuComponents.Count;
  }
  public override string Print(){
   StringBuilder printOutPut = new StringBuilder();
   printOutPut.Append("/n" + name);
   printOutPut.Append(", " + description + "/n");
   printOutPut.Append("-------------------------/n");
   
   foreach(MenuComponent menuComponent in menuComponents){
    printOutPut.Append(menuComponent.Print());
   }

   return printOutPut.ToString();
  }
 }

 public class Waitress{
  MenuComponent allMenus;
  public Waitress(MenuComponent allMenus){
   this.allMenus = allMenus;
  }
  public string PrintMenu(){
   return allMenus.Print();
  }
  public string PrintVegetarianMenu(){
   StringBuilder printOutPut = new StringBuilder();
   printOutPut.Append("/nVEGETARIAN MENU/n");
   printOutPut.Append("-------------------------/n");
   printOutPut.Append(GetChildMenuOutPutDown2Levels(allMenus.GetMenu()));
   return printOutPut.ToString();
  }
  private string GetChildMenuOutPutDown2Levels(ArrayList menus){
   StringBuilder printChildMenuOutPut = new StringBuilder();

   foreach(MenuComponent menuComponent in menus){
    for(int i = 0; i < menuComponent.Count(); i++){
     if(menuComponent.GetChild(i).IsVegetarian){
      printChildMenuOutPut.Append(menuComponent.GetChild(i).Print());
     }

     if(menuComponent.GetChild(i).GetType().Name == "Menu"){
      for(int j = 0; j < menuComponent.GetChild(i).Count(); j++){
       printChildMenuOutPut.Append(menuComponent.GetChild(i).GetChild(j).Print());
      }
     }
    }
   }
   return printChildMenuOutPut.ToString();
  }
 }
    //这样加菜单就非常方便了,
    static void Main(string[] args){
  MenuComponent pancakeHouseMenu;
        pancakeHouseMenu = new Menu("PANCAKE HOUSE MENU","Breakfast");
     pancakeHouseMenu.Add(new MenuItem("1", "1", true, 2.99));

  MenuComponent dinnerMenu;
  dinnerMenu = new Menu("DINNER MENU","Lunch");
        dinnerMenu.Add(new MenuItem("2", "2", true, 2.99));

  MenuComponent allMenus;
        allMenus.Add(pancakeHouseMenu);
        allMenus.Add(dinnerMenu);

  Waitress waitress;
        waitress = new Waitress(allMenus);
        waitress.PrintMenu();
    }
    //菜单中可以增加菜单项,但也可以增加菜单,所以要同一个父节点
    public class MenuItem : MenuComponent
    public class Menu : MenuComponent

三:表明上看起来,上面MenuComponent多余
    public class MenuItem{
        string name;
        string description;
        bool vegetarian;
        double price;

        public MenuItem(string name, string description, bool vegetarian, double price){
            this.name = name;
            this.description = description;
            this.vegetarian = vegetarian;
            this.price = price;
        }
        public string Name{
            get { return name; }
            set { this.name = value; }
        }
        public string Description{
            get { return description; }
            set { this.description = value; }
        }
        public double Price{
            get { return price; }
            set { price = value; }
        }
        public bool IsVegetarian{
            get { return vegetarian; }
            set { this.vegetarian = value; }
        }
    }
    public class Menu{
        ArrayList menuComponents = new ArrayList();
        string name;
        string description;

        public Menu(string name, string description){
            this.name = name;
            this.description = description;
        }
        public string Name{
            get { return name; }
            set { this.name = value; }
        }
        public string Description{
            get { return description; }
            set { this.description = value; }
        }

        public void Add(MenuItem menuComponent){
            menuComponents.Add(menuComponent);
        }

        public void Remove(MenuItem menuComponent){
            menuComponents.Remove(menuComponent);
        }

        public MenuItem GetChild(int i){
            return (MenuItem)menuComponents[i];
        }

        public ArrayList GetMenu(){
            return menuComponents;
        }
        public int Count(){
            return menuComponents.Count;
        }
    }
    class Waitress{
        Menu allMenus;
        public Waitress(Menu allMenus){
            this.allMenus = allMenus;
        }
    }
    static void Main(string[] args)
    {
        Menu pancakeHouseMenu = new Menu("PANCAKE HOUSE MENU", "Breakfast");
        pancakeHouseMenu.Add(new MenuItem("1", "1", true, 2.99));

        Menu dinnerMenu = new Menu("DINNER MENU", "Lunch");
        dinnerMenu.Add(new MenuItem("2", "2", true, 2.99));

        Menu allMenus;
        //如下代码,就通不过
        //菜单作为节点,包含了很多菜单项
        //但同时,菜单之间也可以作为父子节点,
        //所以才存在public class Menu : MenuComponent
        allMenus.Add(pancakeHouseMenu);
        allMenus.Add(dinnerMenu);

        Waitress waitress;
        waitress = new Waitress(allMenus);
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值