Iterator pattern
#region Menu
public class MenuItem
{
public string Name { get; }
public string Description { get; }
public bool IsVegetarian { get; }
public decimal Price { get; }
public MenuItem(string name, string description, bool isVegetarian, decimal price)
{
Name = name;
Description = description;
IsVegetarian = isVegetarian;
Price = price;
}
}
public class PancakeMenu
{
private List<MenuItem> menuItems = new List<MenuItem>();
public PancakeMenu()
{
menuItems.Add(new MenuItem("a", "111", false, 2.99m));
menuItems.Add(new MenuItem("b", "222", false, 2.99m));
menuItems.Add(new MenuItem("c", "333", true, 3.49m));
menuItems.Add(new MenuItem("d", "444", true, 3.59m));
}
public void AddItem(MenuItem item) { menuItems.Add(item); }
public void RemoveItem(MenuItem item) { menuItems.Remove(item); }
public Iterator CreateIterator() { return new PancakeMenuIterator(menuItems); }
}
public class DinerMenu
{
private readonly int MAX_ITEMS = 6;
private int numberOfItems = 0;
private MenuItem[] menuItems;
public DinerMenu()
{
menuItems = new MenuItem[MAX_ITEMS];
menuItems[0] = new MenuItem("e", "555", true, 2.99m);
menuItems[1] = new MenuItem("f", "666", false, 2.99m);
menuItems[2] = new MenuItem("g", "777", false, 3.29m);
menuItems[3] = new MenuItem("h", "888", false, 3.05m);
}
public void AddItem(string name, string description, bool isVegetarian, decimal price)
{
if (numberOfItems < MAX_ITEMS)
{
menuItems[numberOfItems] = new MenuItem(name, description, isVegetarian, price);
numberOfItems++;
}
else { Console.WriteLine("Sorry, menu is full!"); }
}
/*public MenuItem[] GetMenu() { return menuItems; }*/
public Iterator CreateIterator() { return new DinerMenuIterator(menuItems); }
}
#endregion
#region Iterator
public interface Iterator
{
public bool hasNext();
public MenuItem next();
}
public class DinerMenuIterator : Iterator
{
private readonly MenuItem[] menuItems;
private int position = 0;
public DinerMenuIterator(MenuItem[] menuItems)
{
this.menuItems = menuItems;
}
public bool hasNext()
{
if( menuItems[position] == null) return false;
else
return position < menuItems.Length;
}
public MenuItem next()
{
return menuItems[position++];
}
}
public class PancakeMenuIterator : Iterator
{
private readonly List<MenuItem> menuItems;
private int position = 0;
public PancakeMenuIterator(List<MenuItem> menuItems)
{
this.menuItems = menuItems;
}
public bool hasNext() { return position < menuItems.Count; }
public MenuItem next() { return menuItems[position++]; }
}
#endregion
public class Waitress
{
PancakeMenu pancakeMenu;
DinerMenu dinerMenu;
public Waitress(PancakeMenu pancakeMenu, DinerMenu dinerMenu)
{
this.pancakeMenu = pancakeMenu;
this.dinerMenu = dinerMenu;
}
public void PrintMenu()
{
Iterator pancakeIterator = pancakeMenu.CreateIterator();
Iterator dinerIterator = dinerMenu.CreateIterator();
Console.WriteLine("MENU\n----\nBREAKFAST");
PrintMenu(pancakeIterator);
Console.WriteLine("\nLUNCH");
PrintMenu(dinerIterator);
}
private void PrintMenu(Iterator iterator)
{
while (iterator.hasNext())
{
MenuItem item = iterator.next();
Console.WriteLine($"{item.Name}, {item.Price:F2} -- {item.Description}");
}
}
}
public class TestDrive
{
public static void Main(string[] args)
{
PancakeMenu pancakeMenu = new PancakeMenu();
DinerMenu dinerMenu = new DinerMenu();
Waitress waitress = new Waitress(pancakeMenu, dinerMenu);
waitress.PrintMenu();
}
}
어셈블리에서 지원하는 반복자의 경우 IEnumerator<>를 반환형으로, Collection.GetEnumerator()를 사용하면 되는 것 같다.
Diner은 Iterable이 아니어서 Iterator를 직접 구현했다.
#region Menu
using System.Collections;
public class MenuItem
{
public string Name { get; }
public string Description { get; }
public bool IsVegetarian { get; }
public decimal Price { get; }
public MenuItem(string name, string description, bool isVegetarian, decimal price)
{
Name = name;
Description = description;
IsVegetarian = isVegetarian;
Price = price;
}
}
public interface IMenu
{
public void AddItem(MenuItem item);
public void RemoveItem(MenuItem item);
public abstract IEnumerator<MenuItem> CreateIterator();
}
public class PancakeMenu : IMenu
{
private List<MenuItem> menuItems = new List<MenuItem>();
public PancakeMenu()
{
menuItems.Add(new MenuItem("a", "111", false, 2.99m));
menuItems.Add(new MenuItem("b", "222", false, 2.99m));
menuItems.Add(new MenuItem("c", "333", true, 3.49m));
menuItems.Add(new MenuItem("d", "444", true, 3.59m));
}
public void AddItem(MenuItem item) { menuItems.Add(item); }
public void RemoveItem(MenuItem item) { menuItems.Remove(item); }
public IEnumerator<MenuItem> CreateIterator() { return menuItems.GetEnumerator(); }
}
public class DinerMenu : IMenu
{
private readonly int MAX_ITEMS = 6;
private int numberOfItems = 0;
private MenuItem[] menuItems;
public DinerMenu()
{
menuItems = new MenuItem[MAX_ITEMS];
menuItems[0] = new MenuItem("e", "555", true, 2.99m);
menuItems[1] = new MenuItem("f", "666", false, 2.99m);
menuItems[2] = new MenuItem("g", "777", false, 3.29m);
menuItems[3] = new MenuItem("h", "888", false, 3.05m);
}
public void AddItem(string name, string description, bool isVegetarian, decimal price)
{
if (numberOfItems < MAX_ITEMS)
{
menuItems[numberOfItems] = new MenuItem(name, description, isVegetarian, price);
numberOfItems++;
}
else { Console.WriteLine("Sorry, menu is full!"); }
}
public void AddItem(MenuItem item) { throw new NotImplementedException(); }
public void RemoveItem(MenuItem item) { throw new NotImplementedException(); }
public IEnumerator<MenuItem> CreateIterator() { return new DinerMenuIterator(menuItems); }
}
#endregion
#region Iterator
public class DinerMenuIterator : IEnumerator<MenuItem>
{
private readonly MenuItem[] menuItems;
private int position = 0;
private object? _current;
private MenuItem _current1;
public DinerMenuIterator(MenuItem[] menuItems)
{
this.menuItems = menuItems;
}
public bool MoveNext()
{
if( menuItems[position] == null || position >= menuItems.Length) return false;
else
{
_current = menuItems[position];
_current1 = menuItems[position];
position++;
return true;
}
}
public void Reset()
{
throw new NotImplementedException();
}
MenuItem IEnumerator<MenuItem>.Current => _current1;
object? IEnumerator.Current => _current;
public void Dispose()
{
throw new NotImplementedException();
}
}
#endregion
public class Waitress
{
IMenu pancakeMenu;
IMenu dinerMenu;
public Waitress(IMenu pancakeMenu, IMenu dinerMenu)
{
this.pancakeMenu = pancakeMenu;
this.dinerMenu = dinerMenu;
}
public void PrintMenu()
{
IEnumerator<MenuItem> pancakeIterator = pancakeMenu.CreateIterator();
IEnumerator<MenuItem> dinerIterator = dinerMenu.CreateIterator();
Console.WriteLine("MENU\n----\nBREAKFAST");
PrintMenu(pancakeIterator);
Console.WriteLine("\nLUNCH");
PrintMenu(dinerIterator);
}
private void PrintMenu(IEnumerator<MenuItem> iterator)
{
while (iterator.MoveNext())
{
if(iterator.Current == null) break;
MenuItem item = iterator.Current;
Console.WriteLine($"{item.Name}, {item.Price:F2} -- {item.Description}");
}
}
}
public class TestDrive
{
public static void Main(string[] args)
{
IMenu pancakeMenu = new PancakeMenu();
IMenu dinerMenu = new DinerMenu();
Waitress waitress = new Waitress(pancakeMenu, dinerMenu);
waitress.PrintMenu();
}
}
Composite pattern
using System.Collections;
public abstract class MenuComponent
{
protected List<MenuComponent> menuComponents = new List<MenuComponent>();
public string Name { get; protected set; } = string.Empty;
public string Description { get; protected set; } = string.Empty;
public void Add(MenuComponent menuComponent) { menuComponents.Add(menuComponent); }
public void Remove(MenuComponent menuComponent) { menuComponents.Remove(menuComponent); }
public MenuComponent GetChild(int i) { return menuComponents[i]; }
public virtual void Print() { }
}
public class MenuItem : MenuComponent
{
public bool IsVegetarian { get; private set; } = false;
public decimal Price { get; private set; } = 0.0m;
public MenuItem(string name, string description, bool isVegetarian, decimal price)
{
Name = name;
Description = description;
IsVegetarian = isVegetarian;
Price = price;
}
public override void Print()
{
Console.WriteLine($"{Name}, {PrintVegetarian()} {Price:F2} {PrintDescription()}");
if(menuComponents.Count > 0)
{
Console.WriteLine("+ other options");
foreach (var menuComponent in menuComponents) menuComponent.Print();
}
}
private string PrintVegetarian() { return IsVegetarian ? " (V) " : " "; }
private string PrintDescription() { return Description.Length > 0 ? "-- " + Description : "(no description)"; }
}
public class Menu : MenuComponent
{
public Menu(string name, string description)
{
Name = name;
Description = description;
}
public override void Print()
{
Console.WriteLine($"\n{Name}, {Description}\n --------------------------");
foreach (var menuComponent in menuComponents) menuComponent.Print();
}
}
public class Waitress
{
private MenuComponent allMenus;
public Waitress(MenuComponent allMenus) { this.allMenus = allMenus; }
public void PrintMenu() { allMenus.Print(); }
}
public class TestDrive
{
public static void Main(string[] args)
{
MenuComponent pancakeHouseMenu = new Menu("[PANCAKE HOUSE 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);
allMenus.Add(dessertMenu);
MenuItem pancake = new MenuItem("Pancakes", "With fried eggs, sausage", false, 2.99m);
MenuItem waffles = new MenuItem("Waffles", "With your choice of blueberries or strawberries", true, 3.59m);
MenuItem eggsBaconMushroom = new MenuItem("Eggs, Bacon and Mushroom", "Simple menu", true, 3.49m);
MenuItem cake = new MenuItem("Cake", "Chocolate with a chocolate frosting", true, 4.25m);
MenuItem tea = new MenuItem("Tea", "With hot chocolate", true, 1.50m);
MenuItem dessert = new MenuItem("Dessert", "Peach puffs and chocolate syrup", false, 2.50m);
pancakeHouseMenu.Add(pancake);
pancakeHouseMenu.Add(waffles);
dinerMenu.Add(eggsBaconMushroom);
cafeMenu.Add(tea);
dessertMenu.Add(cake);
dessertMenu.Add(dessert);
waffles.Add(new MenuItem(" Blueberries", "", true, 0.99m));
waffles.Add(new MenuItem(" Strawberries", "", true, 1.50m));
dessert.Add(new MenuItem(" Peach puffs", "", true, 1.25m));
dessert.Add(new MenuItem(" Chocolate syrup", "", true, 1.00m));
Waitress waitress = new Waitress(allMenus);
waitress.PrintMenu();
}
}
java의 instancof 키워드는 C#에선 is 키워드다.
해당하는 타입의 인스턴스인지 확인할 수 있다.
public class Animal { }
public class Dog : Animal { }
public class Example
{
public void CheckType(object obj)
{
if (obj is Dog)
{
Console.WriteLine("The object is an instance of Dog.");
}
else
{
Console.WriteLine("The object is not an instance of Dog.");
}
}
}
'코딩 공부 > 디자인패턴' 카테고리의 다른 글
패턴 정리 (0) | 2024.12.09 |
---|---|
프록시 패턴 (1) | 2024.12.09 |
템플릿 메소드 패턴 (0) | 2024.12.05 |
어댑터 패턴, 퍼사드 패턴 (1) | 2024.12.04 |
커맨드 패턴 (0) | 2024.12.04 |