我在复合图案后面有一组对象。它们构成了一个我想用IEnumerator遍历的树结构。我正在翻译书中的一些Java代码" Head First Design Patterns"。我实现了两个实现IEnumerator接口的类: CompositeIterator 和 NullIterator 。
This是我想要转换为C#的java代码。
此外,这是我的wanted implementation of the Waitress class,当我只需要调用 MoveNext()和 Current 来遍历整个树结构时。
现在我的代码没有进入涉及迭代器的while循环,我想在控制台上打印素食 MenuItem 对象。
这是我的代码:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace Iterator
{
class Program
{
static void Main(string[] args)
{
MenuComponent pancakeHouseMenu = new Menu("PANCAKEHOUSE MENU", "Breakfast");
MenuComponent dinerMenu = new Menu("DINER MENU", "Lunch");
MenuComponent cafeMenu = new Menu("CAFE MENU", "Dinner");
MenuComponent dessertMenu = new Menu("DESSERT MENU", "Dessert of course!");
MenuComponent allMenus = new Menu("ALL MENUS", "All menus combined");
allMenus.Add(pancakeHouseMenu);
allMenus.Add(dinerMenu);
allMenus.Add(cafeMenu);
pancakeHouseMenu.Add(new MenuItem("K&B Pancake breakfast", "pancakes with scrambled eggs, and toast", true, 2.99));
pancakeHouseMenu.Add(new MenuItem("Regular Pancake breakfast", "pancakes with fried eggs, sausage", false, 2.99));
dinerMenu.Add(new MenuItem("Veggie burguer and air fries", "Veggie burguer on a whole wheat bun, lettuce, tomato and fries", true, 3.99));
dinerMenu.Add(new MenuItem("Soup of the day", "Soup of the day with a side salad", false, 3.69));
dinerMenu.Add(dessertMenu);
dessertMenu.Add(new MenuItem("Apple pie", "Apple pie with a flakey crust, topped with vanilla ice cream", true, 1.59));
cafeMenu.Add(new MenuItem("Vegetarian BLT", "(Fakin') Bacon with lettuce & tomato on whole wheat", true, 2.99));
cafeMenu.Add(new MenuItem("BLT", "Bacon with lettuce & tomato on whole wheat", false, 2.99));
Waitress waitress = new Waitress(allMenus);
waitress.PrintVegetarianMenu();
}
}
class Waitress
{
private MenuComponent AllMenus { get; set; }
public Waitress(MenuComponent allMenus)
{
AllMenus = allMenus;
}
public void PrintMenu()
{
AllMenus.Print();
}
public void PrintVegetarianMenu()
{
CompositeIterator<MenuComponent> iterator = (CompositeIterator<MenuComponent>)AllMenus.CreateIterator();
Console.WriteLine("VEGATARIAN MENU");
// this loop is never entered
while (iterator.MoveNext())
{
Console.WriteLine("inside while loop");
MenuComponent menuComponent = (MenuComponent)iterator.Current;
Console.WriteLine(menuComponent.Name);
try
{
if (menuComponent.Vegetarian)
{
menuComponent.Print();
}
}
catch (NotSupportedException e)
{
Console.WriteLine("Operation not supported.");
}
}
}
}
/*
Methods of MenuComponent class are virtual, because we sometimes want to use the default behavior. The CreateIterator method is abstract.
*/
abstract class MenuComponent
{
// Composite methods
public virtual void Add(MenuComponent menuComponent)
{
throw new NotSupportedException();
}
public virtual void Remove(MenuComponent menuComponent)
{
throw new NotSupportedException();
}
public virtual MenuComponent GetChild(int i)
{
throw new NotSupportedException();
}
// End of composite methods
// Operation methods
public virtual string Name
{
get
{
throw new NotSupportedException();
}
set
{
throw new NotSupportedException();
}
}
public virtual string Description
{
get
{
throw new NotSupportedException();
}
set
{
throw new NotSupportedException();
}
}
public virtual bool Vegetarian
{
get
{
throw new NotSupportedException();
}
set
{
throw new NotSupportedException();
}
}
public virtual double Price
{
get
{
throw new NotSupportedException();
}
set
{
throw new NotSupportedException();
}
}
public virtual void Print()
{
throw new NotSupportedException();
}
// End of operation methods
public abstract IEnumerator CreateIterator();
}
public sealed class CompositeIterator<T> : IEnumerator<T> {
private readonly Stack<IEnumerator<T>> Stack = new Stack<IEnumerator<T>>();
public CompositeIterator(IEnumerator<T> initial)
{
Stack.Push(initial);
}
public bool MoveNext()
{
while (Stack.Any())
{
if (!Stack.Peek().MoveNext())
{
Stack.Pop().Dispose();
continue;
}
var tmp = Current as IEnumerable<T>;
if (tmp != null) { Stack.Push(tmp.GetEnumerator()); }
}
return false;
}
public void Reset() { throw new NotSupportedException(); }
public T Current => Stack.Peek() != null ? Stack.Peek().Current : default(T);
object IEnumerator.Current => Current;
public void Dispose()
{
if (!Stack.Any()) { return; }
try {
foreach (var x in Stack) {
x.Dispose();
}
} catch { }
}
}
public sealed class NullIterator<T> : IEnumerator<T> {
public NullIterator() {}
public bool MoveNext()
{
return false;
}
public void Reset() { throw new NotSupportedException(); }
public T Current
{
get
{
return default(T);
}
}
object IEnumerator.Current => Current;
public void Dispose()
{
return;
}
}
// This is a tree leaf
class MenuItem : MenuComponent
{
public override string Name { get; set; }
public override string Description { get; set; }
public override bool Vegetarian { get; set; }
public override double Price { get; set; }
public MenuItem(string name, string description, bool vegetarian, double price)
{
Name = name;
Description = description;
Vegetarian = vegetarian;
Price = price;
}
public override void Print()
{
Console.Write(" " + Name);
if (Vegetarian)
{
Console.Write("(v)");
}
Console.Write(", " + Price);
Console.Write(" -- " + Description);
}
public override IEnumerator CreateIterator()
{
return new NullIterator<MenuItem>();
}
}
// This is a tree node
class Menu : MenuComponent
{
public List<MenuComponent> MenuComponents;
public override string Name { get; set; }
public override string Description { get; set; }
public Menu(string name, string description)
{
Name = name;
Description = description;
MenuComponents = new List<MenuComponent>();
}
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 MenuComponents[i];
}
// we have to use recursion to print all the hierarchy
public override void Print()
{
Console.Write("\n" + Name);
Console.WriteLine(", " + Description);
Console.WriteLine("--------------");
IEnumerator iterator = MenuComponents.GetEnumerator();
while(iterator.MoveNext())
{
MenuComponent menuComponent = (MenuComponent)iterator.Current;
menuComponent.Print();
Console.Write("\n");
}
}
public override IEnumerator CreateIterator()
{
return new CompositeIterator<MenuComponent>(MenuComponents.GetEnumerator());
}
}
}
答案 0 :(得分:0)
这是我最接近你想要的东西而不用创建我自己的迭代器。我觉得不需要重新编码dotnet框架中已经存在的内容。
class Program
{
static void Main(string[] args)
{
//var all = new Menu("ALL SECTIONS", "All menu sections");
var pancakeHouseMenu = new Menu("PANCAKEHOUSE MENU", "Breakfast",
new MenuSection("PANCAKES", "Breakfast Pancakes Selection",
new MenuItem("K&B Pancake breakfast", "pancakes with scrambled eggs, and toast", true, 2.99m),
new MenuItem("Regular Pancake breakfast", "pancakes with fried eggs, sausage", false, 2.99m)));
var dinnerMenu = new Menu("DINNER MENU", "Lunch",
new MenuSection("","",
new MenuItem("Veggie burger and air fries", "Veggie burguer on a whole wheat bun, lettuce, tomato and fries", true, 3.99m),
new MenuItem("Soup of the day", "Soup of the day with a side salad", false, 3.69m)));
var cafeMenu = new Menu("CAFE MENU", "Dinner",
new MenuSection("", "",
new MenuItem("Vegetarian BLT", "(Fakin') Bacon with lettuce & tomato on whole wheat", true, 2.99m),
new MenuItem("BLT", "Bacon with lettuce & tomato on whole wheat", false, 2.99m)),
new MenuSection("DESSERT MENU", "Dessert of course!",
new MenuItem("Apple pie", "Apple pie with a flakey crust, topped with vanilla ice cream", true, 1.59m)));
var waiter = new Waitress(pancakeHouseMenu, dinnerMenu, cafeMenu);
//waiter.Print();
//waiter.PrintVegenerian();
WriteFileAndOpenNotepad(waiter.ToString());
WriteFileAndOpenNotepad(waiter.ToVegetarianString());
}
static void WriteFileAndOpenNotepad(string text)
{
var fn = Path.GetTempFileName();
fn=Path.ChangeExtension(fn, ".txt");
File.WriteAllText(fn, text);
Process.Start(fn);
}
}
public abstract class MenuComponent
{
public string Description { get; private set; }
public string Name { get; private set; }
protected MenuComponent(string name, string description)
{
this.Name=name;
this.Description=description;
}
public abstract override string ToString();
public void Print()
{
Console.WriteLine(ToString());
}
}
public class MenuItem : MenuComponent
{
public MenuItem(string name, string description, bool vegeterian, decimal price)
: base(name, description)
{
this.Price=price;
this.Vegetarian=vegeterian;
}
public decimal Price { get; set; }
public bool Vegetarian { get; set; }
public override string ToString()
{
//Use 28 columns for the item name
return string.Format("{0,28}{1}, {2} -- {3}",
Name, Vegetarian ? "(v)" : " ", Price, Description);
}
}
public class MenuSection : MenuComponent
{
public MenuSection(string name, string description, params MenuItem[] items)
: this(name, description, items as IEnumerable<MenuItem>)
{ }
public MenuSection(string name, string description, IEnumerable<MenuItem> items) : base(name, description)
{
this.Items=new List<MenuItem>(items);
}
public List<MenuItem> Items { get; private set; }
public override string ToString()
{
var sb = new StringBuilder();
sb.AppendLine();
if(Name.Length>0)
{
sb.AppendFormat("{0}, {1}", Name, Description);
sb.AppendLine();
sb.AppendLine("--------------");
}
foreach(var item in Items)
{
sb.AppendLine();
sb.AppendLine(item.ToString());
}
return sb.ToString();
}
public MenuSection VegeterianSections
{
get
{
var veg = Items.Where((item) => item.Vegetarian);
return new MenuSection(Name, Description, veg);
}
}
}
public class Menu : MenuComponent
{
public Menu(string name, string description, IEnumerable<MenuSection> sections)
: base(name, description)
{
this.MenuSections=new List<MenuSection>(sections);
}
public Menu(string name, string description, params MenuSection[] sections)
: this(name, description, sections as IEnumerable<MenuSection>)
{ }
public List<MenuSection> MenuSections { get; private set; }
public override string ToString()
{
var sb = new StringBuilder();
sb.AppendLine();
sb.AppendFormat("[{0}, {1}]", Name, Description);
sb.AppendLine();
sb.AppendLine("==============");
foreach(var section in MenuSections)
{
sb.AppendLine();
sb.AppendLine(section.ToString());
}
return sb.ToString();
}
public Menu VegeraterianMenu
{
get
{
return new Menu(Name, Description, MenuSections.Select((section)=> section.VegeterianSections));
}
}
}
public class Waitress
{
public Waitress(params Menu[] all)
{
this.AllMenus=new List<Menu>(all);
this.VegeratianMenu=all.Select((menu)=>menu.VegeraterianMenu).ToList();
}
public IList<Menu> AllMenus { get; private set; }
public IList<Menu> VegeratianMenu { get; private set; }
public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("*** A L L I T E M S ***");
foreach(var item in AllMenus)
{
sb.AppendLine("************************");
sb.AppendLine(item.ToString());
}
return sb.ToString();
}
public string ToVegetarianString()
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("*** V E G I T E M S ***");
foreach(var item in VegeratianMenu)
{
sb.AppendLine("************************");
sb.AppendLine(item.ToString());
}
return sb.ToString();
}
public void Print()
{
Console.WriteLine(ToString());
}
public void PrintVegenerian()
{
Console.WriteLine(ToVegetarianString());
}
}
答案 1 :(得分:0)
在与C#freenode IRC频道联系之后,其中一个人给了我一个比书中更好的解决方案和我在这里得到的答案。这是代码,有了这个答案,我希望很清楚我想要的是什么:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace Iterator
{
class Program
{
static void Main(string[] args)
{
MenuComponent pancakeHouseMenu = new Menu("PANCAKEHOUSE MENU", "Breakfast");
MenuComponent dinerMenu = new Menu("DINER MENU", "Lunch");
MenuComponent cafeMenu = new Menu("CAFE MENU", "Dinner");
MenuComponent dessertMenu = new Menu("DESSERT MENU", "Dessert of course!");
MenuComponent allMenus = new Menu("ALL MENUS", "All menus combined");
allMenus.Add(pancakeHouseMenu);
allMenus.Add(dinerMenu);
allMenus.Add(cafeMenu);
pancakeHouseMenu.Add(new MenuItem("K&B Pancake breakfast", "pancakes with scrambled eggs, and toast", true, 2.99));
pancakeHouseMenu.Add(new MenuItem("Regular Pancake breakfast", "pancakes with fried eggs, sausage", false, 2.99));
dinerMenu.Add(new MenuItem("Veggie burguer and air fries", "Veggie burguer on a whole wheat bun, lettuce, tomato and fries", true, 3.99));
dinerMenu.Add(new MenuItem("Soup of the day", "Soup of the day with a side salad", false, 3.69));
dinerMenu.Add(dessertMenu);
dessertMenu.Add(new MenuItem("Apple pie", "Apple pie with a flakey crust, topped with vanilla ice cream", true, 1.59));
cafeMenu.Add(new MenuItem("Vegetarian BLT", "(Fakin') Bacon with lettuce & tomato on whole wheat", true, 2.99));
cafeMenu.Add(new MenuItem("BLT", "Bacon with lettuce & tomato on whole wheat", false, 2.99));
cafeMenu.Add(dessertMenu);
Waitress waitress = new Waitress(allMenus);
waitress.PrintVegetarianMenu();
}
}
class Waitress
{
private MenuComponent AllMenus { get; set; }
public Waitress(MenuComponent allMenus)
{
AllMenus = allMenus;
}
public void PrintMenu()
{
AllMenus.Print();
}
public void PrintVegetarianMenu()
{
Console.WriteLine("VEGATARIAN MENU");
foreach (MenuComponent menuComponent in AllMenus)
{
try
{
if (menuComponent.Vegetarian)
{
menuComponent.Print();
Console.Write("\n");
}
}
catch (NotSupportedException)
{
Console.WriteLine("Operation not supported.");
}
}
}
}
abstract class MenuComponent : IEnumerable<MenuComponent>
{
// Composite methods
public abstract void Add(MenuComponent menuComponent);
public abstract void Remove(MenuComponent menuComponent);
public abstract MenuComponent GetChild(int i);
// End of composite methods
// Operation methods
public virtual string Name { get; set; }
public virtual string Description { get; set; }
public virtual bool Vegetarian { get; set; }
public virtual double Price { get; set; }
public abstract void Print();
public abstract IEnumerator<MenuComponent> GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
/// This is a tree leaf
class MenuItem : MenuComponent
{
public MenuItem(string name, string description, bool vegetarian, double price)
{
Name = name;
Description = description;
Vegetarian = vegetarian;
Price = price;
}
public override void Print()
{
Console.Write(" " + Name);
if (Vegetarian)
{
Console.Write("(v)");
}
Console.Write(", " + Price);
Console.Write(" -- " + Description);
}
public override IEnumerator<MenuComponent> GetEnumerator()
{
yield break;
}
public override void Add(MenuComponent menuComponent)
{
throw new NotSupportedException();
}
public override void Remove(MenuComponent menuComponent)
{
throw new NotSupportedException();
}
public override MenuComponent GetChild(int i)
{
throw new NotSupportedException();
}
}
/// This is a tree node
class Menu : MenuComponent
{
private List<MenuComponent> MenuComponents;
public Menu(string name, string description)
{
Name = name;
Description = description;
MenuComponents = new List<MenuComponent>();
}
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 MenuComponents[i];
}
// we have to use recursion to print all the hierarchy
public override void Print()
{
Console.Write("\n" + Name);
Console.WriteLine(", " + Description);
Console.WriteLine("--------------");
foreach (MenuComponent menuComponent in MenuComponents)
{
menuComponent.Print();
Console.Write("\n");
}
}
public override IEnumerator<MenuComponent> GetEnumerator()
{
var components = new Stack<MenuComponent>(new[] { this });
while (components.Any())
{
MenuComponent component = components.Pop();
yield return component;
var menu = component as Menu;
if (menu != null)
{
foreach (var n in menu.MenuComponents) components.Push(n);
}
}
}
}
}