如果我有一个工厂方法,不同的实现需要不同的参数,我该怎么办?
我有一个接口 IMessage
和一个类,其中有多种方法用于创建不同类型的消息,如下所示:
class MessageService
{
IMessage TypeAMessage(param 1, param 2)
IMessage TypeBMessage(param 1, param 2, param 3, param 4)
IMessage TypeCMessage(param 1, param 2, param 3)
IMessage TypeDMessage(param 1)
}
我不希望此类完成创建这些消息的所有工作,因此它只是委托给一个 MessageCreatorFactory
,它根据给定的类型生成一个 IMessageCreator
(基于消息 TypeA、TypeB、TypeC 等类型的枚举)
interface IMessageCreator
{
IMessage Create(MessageParams params);
}
所以我有 4 个 的实现>IMessageCreator
:TypeAMessageCreator
、TypeBMessageCreator
、TypeCMessageCreator
、TypeDMessageCreator
我对此表示同意,除了事实因为每种类型需要不同的参数,所以我必须创建一个 MessageParams
对象,其中包含 4 个不同参数的 4 个属性,但每个 IMessageCreator
中只使用其中的一些属性。
有替代方案吗?我的另一个想法是在 Create 方法中使用一个参数数组作为参数,但这似乎更糟糕,因为您不知道参数是什么。或者在接口中创建 Create 的多个重载,如果它们不适合该特定实现,则让其中一些重载抛出异常(即您调用了需要更多参数的方法,因此您应该调用其他重载之一。)
这看起来可以吗?有更好的解决方案吗?
I have an interface, IMessage
and a class which have several methods for creating different types of message like so:
class MessageService
{
IMessage TypeAMessage(param 1, param 2)
IMessage TypeBMessage(param 1, param 2, param 3, param 4)
IMessage TypeCMessage(param 1, param 2, param 3)
IMessage TypeDMessage(param 1)
}
I don't want this class to do all the work for creating these messages so it simply delegates to a MessageCreatorFactory
which produces an IMessageCreator
depending on the type given (an enumeration based on the type of the message TypeA, TypeB, TypeC etc)
interface IMessageCreator
{
IMessage Create(MessageParams params);
}
So I have 4 implementations of IMessageCreator
: TypeAMessageCreator
, TypeBMessageCreator
, TypeCMessageCreator
, TypeDMessageCreator
I ok with this except for the fact that because each type requires different parameters I have had to create a MessageParams
object which contains 4 properties for the 4 different params, but only some of them are used in each IMessageCreator
.
Is there an alternative to this? One other thought I had was to have a param array as the parameter in the Create method, but this seems even worse as you don't have any idea what the params are. Or to create several overloads of Create in the interface and have some of them throw an exception if they are not suitable for that particular implementation (ie you called a method which needs more params, so you should have called one of the other overloads.)
Does this seem ok? Is there a better solution?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这确实违反了工厂方法模式的精神。如果您需要不同的参数来构造不同的类型,则隐式地强制调用者提前知道正在构造什么类型。这完全消除了这种模式的好处。
例如,如果您指定一个枚举(TypeA、TypeB、TypeC),您也可以直接构造 TypeA。如果你想允许多个子类实现TypeA,就为TypeA创建一个工厂......
This is really a violation of the spirit of the Factory method pattern. If you require different parameters for the construction of your different types, you're implicitly forcing the caller to know, in advance, what type is being constructed. This completely eliminates the benefit of this pattern.
For example, if you're specifying an enum (TypeA, TypeB, TypeC), you might as well just construct TypeA directly. If you want to allow multiple subclasses to implement TypeA, make a factory just for TypeA...
在我看来,拥有四个 IMessage Create 重载比拥有一个包含 MessageParam 的方法要好得多。
只需为创建者的实现不支持的那些方法抛出异常即可。
因此,当您再次打开代码时,您可能会在一周或一个月内受益匪浅。这个实现对你来说比当前的实现更明显
In my oppinion having four overloads of IMessage Create is much better then having one method with MessageParam in it.
Just throw an exception for those methods that are not supporting by the implementation of creator.
As result you will have great benefit in probably a week or a month when you open your code again. This implementation will be more obvious to you then the current one
我不明白为什么您的
TypeXMessageCreator
类应该实现通用接口。我会完全摆脱IMessageCreator
,只用 4 个独立的工厂来创建IMessage
对象。如果
IMessage
对象的创建需要一些通用逻辑,您可以将该逻辑放在一个单独的类中并在工厂内使用它。请记住,继承不是为了代码重用。
I don't see any reason why your
TypeXMessageCreator
classes should implement a common interface. I would get rid ofIMessageCreator
entirely, and just have 4 separate factories to createIMessage
objects.If the creation of
IMessage
objects requires some common logic, you can put that logic in a separate class and use it from within the factories.Remember that inheritance is not for code reuse.