我有以下示例代码。我已经创建了一个简单的例子来说明我的挑战。
我不确定这种模式的用途,因为我并不完全了解这些模式(但我很想学习)。
我有许多IItem类型的物品。这个例子是食品。
我有一个公共界面(IChef),其职责是获取制作特定项目的所有成分。我已经实现了这个界面Chef。
然后,我有一个内部接口(IKitchenHelper),用于使用泛型类型参数定义的通用项类型。内部接口的职责是准备项目。如果一个项目需要专家准备,那么我已经为该项目创建了一个实现IKitchenHelper的类,否则就有一个GeneralKitchenHelper。
Chef实现有一个私有方法,此方法需要获取相应的厨房助手,调用它的GetPreparedItems并建立所需项目所需的所有项目的列表。如果项有子项,私有方法需要递归调用自身。
我坚持如何找到合适的厨房帮手。我从一个工厂类开始,它维护了一个列表,列出了哪些类型需要厨房帮手。然后我尝试使用Activator.CreateInstance创建适当的KitchenHelper,但是我得到了一个强制转换异常,因为BeansOnToastSpecialist无法转换为IKitchenHelper。
我希望没有静态类并且可能使用DI,但我确保如何实现这一点。我之前在构造函数注入中使用过DI,但是,使用构造函数注入在这种情况下不能工作我相信Chef会需要一些不同的厨房助手。
任何帮助,建议将不胜感激。
public enum ItemType
{
Tomatoes,
Toast,
NavyBeans,
BakedBeans,
BeansOnToast
}
public interface IItem
{
ItemType ItemType { get; }
List<IItem> SubItems { get; }
bool IsPrepared { get; set; }
}
public class GeneralItem : IItem
{
public GeneralItem(ItemType itemType)
{
this.ItemType = itemType;
SubItems = new List<IItem>();
}
public ItemType ItemType { get; }
public List<IItem> SubItems { get; }
public bool IsPrepared { get; set; }
}
public class BakedBeans : IItem
{
public BakedBeans()
{
SubItems = new List<IItem>
{
new GeneralItem(ItemType.Tomatoes),
new GeneralItem(ItemType.NavyBeans),
};
}
public ItemType ItemType => ItemType.BakedBeans;
public List<IItem> SubItems { get; }
public bool IsPrepared { get; set; }
}
public class BeansOnToast : IItem
{
public BeansOnToast()
{
SubItems = new List<IItem>
{
new GeneralItem(ItemType.Toast),
new BakedBeans()
};
}
public ItemType ItemType => ItemType.BeansOnToast;
public List<IItem> SubItems { get; }
public bool IsPrepared { get; set; }
}
public interface IChef
{
List<IItem> GetAllIngredients(IItem item);
}
public class Chef : IChef
{
public List<IItem> GetAllIngredients(IItem item)
{
var items = new List<IItem>();
GetIngredients(items, item);
return items;
}
private static void GetIngredients(List<IItem> items, IItem item)
{
//get appropriate kitchen helper for the passed in item
var myHelper = KitchenHelperDictionary.GetAppropriateHelper(item.ItemType);
foreach (var preparedItem in myHelper.GetPreparedItems(item.ItemType))
{
//TODO: (ensure sub items are not already in the list)
items.Add(preparedItem);
if (item.SubItems.Count == 0) continue;
//call method recursively for all the items subitems
foreach (var itemSubItem in item.SubItems)
{
GetIngredients(items, itemSubItem);
}
}
}
}
public static class KitchenHelperDictionary
{
private static Dictionary<ItemType, Type> allKitchenHelpers =
new Dictionary<ItemType, Type>
{
{ItemType.BakedBeans, typeof(BeansSpecialist)},
{ItemType.BeansOnToast, typeof(BeansOnToastSpecialist)},
};
public static IKitchenHelper<IItem> GetAppropriateHelper(ItemType itemType)
{
//if item type is in the dictionary return a kitchen helper of that type
//else return a generalist kitchen helper
}
}
internal interface IKitchenHelper<T> where T : IItem
{
List<T> GetPreparedItems(ItemType itemType);
}
public class GeneralKitchenHelper : IKitchenHelper<IItem>
{
public List<IItem> GetPreparedItems(ItemType itemType)
{
var items = new List<IItem>();
var item = new GeneralItem(itemType) {IsPrepared = true};
items.Add(item);
return items;
}
}
public class BeansSpecialist : IKitchenHelper<BakedBeans>
{
public List<BakedBeans> GetPreparedItems(ItemType itemType)
{
var items = new List<BakedBeans>();
var item = new BakedBeans {IsPrepared = true};
items.Add(item);
return items;
}
}
public class BeansOnToastSpecialist : IKitchenHelper<BeansOnToast>
{
public List<BeansOnToast> GetPreparedItems(ItemType itemType)
{
var items = new List<BeansOnToast>();
var item = new BeansOnToast {IsPrepared = true};
items.Add(item);
return items;
}
}