如果你的规则都不能变得比简单更复杂比较属性,你可能想留下一个选项来做更多的事情,例如:
interface IFactoryRule
{
bool CanInstantiate(PropertySet propSet);
}
然后
简单的实现方式是这样的:
// compares property set to given parameters
public SimpleRule : IFactoryRule
{
private readonly int a,b,c;
public SimpleRule(a,b,c) { ... }
public bool CanInstantiate(PropertySet propSet)
{
return
propSet.a == a &&
propSet.b == b &&
propSet.c == c;
}
}
但你也可以创建任何类型的复杂的自定义规则:
// compares property set using a delegate
public ComplexRule : IFactoryRule
{
private readonly Func<PropertySet, bool> _func;
public ComplexRule(func) { ... }
public bool CanInstantiate(PropertySet propSet)
{
return _func(propSet);
}
}
各种决定添加到您的工厂:
public class MyClassFactory
{
private static List<Tuple<IFactoryRule, Func<IMyClass>>> _rules = new List();
static MyClassFactory()
{
// rules are evaluated in this same order
_rules.Add(new SimpleRule(1,2,3),() => new Simple());
_rules.Add(new ComplexRule(p => p.a + p.b == p.c),() => new Complex());
}
public static IMyClass Create(PropertySet pset)
{
if (pset == null)
throw new ArgumentNullException("pset");
// try to find a match
Tuple<IFactoryRule, Func<IMyClass>> rule =
_rules.FirstOrDefault(r => r.First.CanInstantiate(pset));
if (rule == null)
throw new ArgumentException(
"Unsupported property set: " + pset.ToString());
// invoke constructor delegate
return rule.Second();
}
}
[编辑:加入MyClassFactory.Create
方法]
正如你可以看到,有一个在该溶液中的规则没有散列映射,因此规则列表中Create
方法进行评价逐个(FirstOrDefault
将遍历该列表直到找到第一场比赛)。
如果您有很多规则(超过20个),并且您正在实例化一百万个对象,您会注意到与HashSet
解决方案相比的速度差异(但这两种方法实际上无法进行比较,因为哈希集只能做平等比较)。
其他那是,用法类似于Andrew's solution:
IMyClass instance = MyClassFactory.Create(propSet);
你可以使用C#吗?如果是这样,你可以做一些语言特定的事情,让你的生活更轻松,即MEF和泛型... – BrandonZeider 2011-04-28 13:02:56
我受MEF使用限制,但不是泛型 - 我很想看一个例子吗? – MalcomTucker 2011-04-28 13:07:21
看起来你有很多建议。 MEF是我最喜欢的方式来解决这个问题,对你的限制太糟糕了。我的博客上有几个简单的工厂示例(http://BrandonZeider.me),包括使用MEF和泛型。如果我是你,我会使用地图和抽象工厂实现。 – BrandonZeider 2011-04-28 13:15:09