Ach*_*les 19 .net design-patterns
我一直在阅读有关设计模式的一些内容,并想要一些观点.考虑以下:
Dim objGruntWorker as IGruntWorker
if SomeCriteria then
   objGruntWorker = new GoFor()
else if SomeOtherCriteria then
   objGruntWorker = new Newb()
else if SomeCriteriaAndTheKitchenSink then
   objGruntWorker = new CubeRat()
end if
objGruntWorker.GetBreakfast()
system.threading.thread.sleep(GetMilliSecondsFromHours(4))
objGruntWorker.GetLunch()
每次出现新标准时,上述代码都会增长.我已经看到了这样的代码,并且无知中自己写了一些代码.该如何解决?这种反模式是否具有更"正式"的名称?谢谢你的帮助!
编辑:另一个考虑因素是我想避免重新编译现有的IGruntWorker简单添加新实现的实现.
这种逻辑通常使用Factory方法模式封装.(请参阅Encapsulation下的ImageReaderFactory示例.)
适合上述解决方案的模式类型是工厂模式.你有一种情况,你不需要知道你需要的具体类型的对象,它只需要实现IGruntWorker.因此,您创建一个接受标准的工厂,并根据该条件返回特定IGruntWorker对象.将标准映射到某个标识符通常是一个好主意,即枚举或常数以便于阅读,例如
public enum WorkerType
{
    Newbie,
    Average,
    Expert
}
public class WorkerFactory
{
    public static IGruntWorker GetWorker(WorkerType type)
    {
        switch (type)
        {
            case WorkerType.Newbie:
                 return new NewbieWorker();
            case WorkerType.Average:
                 return new AverageWorker();
            case WorkerType.Expert:
                 return new ExpertWorker();
        }
    }
}
因此,在您的情况下,您可以使用一个小帮助方法,根据条件计算出所需的正确类型的Worker.这甚至可以包含在您只是传递到工厂的只读属性中.
您可以为每个对象类型创建工厂,并且这些工厂可以具有将标准作为参数的函数,并且如果满足参数则返回IGruntWorker(否则返回null).
然后你可以创建一个这些工厂的列表并循环遍历它们(抱歉,我是ac#guy):
Dim o as IGruntWorker;
foreach (IGruntWorkerFactory f in factories)
{
    o = f.Create(criterias);
    if (o != null)
        break;
}
当需要新标准时,您只需将其添加到工厂列表中,无需修改循环.
可能有一些更美丽的方式
我的2美分
如果您使用 .NET,则可以使用反射来构建它。例如,如果您正在创建一个插件系统,那么您将有一个文件夹来放置插件 DLL。然后,您的工厂将查看可用的 DLL,检查每个 DLL 是否有适当的反射属性,然后将这些属性与传入的任何字符串进行匹配,以决定选择和调用哪个对象。
这使您不必重新编译主应用程序,尽管您必须在其他 DLL 中构建工作程序,然后有一种方法告诉您的工厂使用哪一个。
这里有一些非常快速但肮脏的伪代码来说明这一点:
假设您有一个名为 Workers.DLL 的 DLL 程序集
使用名为 Name 的字符串属性设置名为 WorkerTypeAttribute 的属性,以及能够设置该 Name 属性的构造函数。
[AttributeUsage(AttributeTargets.Class, AllowMultiple=false)]
public class WorkerTypeAttribute : Attribute
{
    string _name;
    public string Name { get { return _name; } }
    public WorkerTypeAttribute(string Name)
    {
        _name = Name;
    }
}
然后,您可以将此属性应用于您定义的任何工作类,如下所示:
[WorkerType("CogWorker")]
public class CogWorker : WorkerBase {}
然后在应用程序的工作工厂中,您将编写如下代码:
 public void WorkerFactory(string WorkerType)
    {
        Assembly workers = Assembly.LoadFile("Workers.dll");
        foreach (Type wt in workers.GetTypes())
        { 
            WorkerTypeAttribute[] was = (WorkerTypeAttribute[])wt.GetCustomAttributes(typeof(WorkerTypeAttribute), true);
            if (was.Count() == 1)
            {
                if (was[0].Name == WorkerType)
                { 
                    // Invoke the worker and do whatever to it here.
                }
            }
        }
    }
我确信还有其他示例可以说明如何执行此操作,但如果您需要更多指示,请告诉我。关键是您的所有工作人员都需要有一个共同的父级或接口,以便您可以以相同的方式调用它们。(即,您的所有工作人员都需要一个通用的“执行”方法或可以从工厂或您使用该对象的任何地方调用的方法。
| 归档时间: | 
 | 
| 查看次数: | 754 次 | 
| 最近记录: |