有很多方法可以在代码中实现这一点,但在我看来,这是在编程之前解决问题的最佳方法:
定义零件和产品(预代码)
在定义所有“部件”时,识别部件的层次结构和分类至关重要。这是正确的,因为某些规则可能是独特的部分(例如“仅棕色芥末”),一些分类(例如“所有芥末”),一些按类型(例如“所有调味品”)等。
构建规则集(预代码)
为每个独特的零件、类别、类型和成品定义规则集(先决条件、排除项等)。
这听起来可能很愚蠢,但必须非常小心,以确保在适当的范围内定义规则。例如,如果成品是Burger
:
- 唯一物品规则 - “蘑菇仅适用于选择蓝纹奶酪”
prerequisite
- 分类规则 - “只能选择 1 种芥末”
exclusive
- 类型规则 - “泡菜与辣椒不相容”
exclusive
在花了这么多时间研究“零件”的独特/类别/类型规则之后,许多设计师会忽略仅适用于成品的规则,即使零件没有冲突。
- 产品规则 - “最多 5 种调味品”
condition
- 产品规则 - “汉堡必须有面包”
prerequisite
这个规则图可以很快变得非常复杂。
构建数据结构的建议(代码)
确保您的结构适应层次结构和分类。例如:“brown mustard”和“dijon mustard”是单独的对象,它们都是芥末,都是调味品。
仔细选择继承建模(基类)和对象属性(例如Category
属性或HasCondiments
标志)的正确组合来完成这项工作。
在每个分层对象级别创建一个私有字段。RuleSets
为标志和集合创建公共属性。HasConflicts
RuleViolations
将零件添加到产品时,检查所有级别的规则(其自身、类别、类型和产品)——通过可以从产品调用的公共函数来执行此操作。或者为了更好地内化,您可以在部件本身上创建一个事件处理程序。
编写你的算法(代码)
这就是我很糟糕的地方,这是一件好事,因为它有点超出了你的问题范围。
这一步的诀窍是如何在代码中实现沿树/图向上传播的规则——例如,当特定部分与超出其范围的另一部分存在问题时,或者当另一部分运行时如何运行验证添加?我的想法:
对每个部分使用公共函数方法。CurrentParts
将产品集合传递给它。
在 Product 对象上,定义处理程序来处理OnPartAdded
and OnPartRemoved
,并让它们枚举CurrentParts
集合并调用每个部分的验证函数。
示例准系统原型
interface IProduct
{
void AddPart();
void OnAddPart();
}
// base class for products
public class Product() : IProduct
{
// private or no setter. write functions as you like to add/remove parts.
public ICollection<Part> CurrentParts { get; };
// Add part function adds to collection and triggers a handler.
public void AddPart(Part p)
{
CurrentParts.Add(p);
OnAddParts();
}
// handler for adding a part should trigger part validations
public void OnAddPart()
{
// validate part-scope rules, you'll want to return some message/exception
foreach(var part in CurrentParts) {
part.ValidateRules(CurrentParts);
}
ValidateRules(); // validate Product-scope rules.
}
}
interface IProduct
{
// "object" should be replaced with whatever way you implement your rules
void object RuleSet;
void ValidateRules(ICollection<Part> otherParts);
}
// base class for parts
public class Part : IPart
{
public object RuleSet; // see note in interface.
public ValidateRules(ICollection<Part> otherParts)
{
// insert your algorithms here for validating
// the product parts against this part's rule set.
}
}
干净整洁。