下面是一篇关于.net框架模式使用的文章。我不确定我是否理解下面摘录中的粗体部分。是否暗示如果更改创建对象的细节,您(可能)更改构造函数参数?
您在框架中有很多案例 可以获取结构或类的新实例 没有自己调用它的构造函数。该 System.Convert类包含一个静态主机 像这样工作的方法。转换整数 例如,你可以调用一个布尔值 Convert.ToBoolean并传入整数。该 此方法调用的返回值是一个新的布尔值 如果整数不为零,则设置为“true” 否则“假”。 Convert类创建 具有正确值的布尔值。其他类型 转换方法类似。解析 Int32和Double上的方法返回新实例 那些对象设置为适当的值 只给一个字符串。
这种创建新对象实例的策略是 称为工厂模式。而不是调用 对象的构造函数,你可以问对象 工厂为您创建实例。那样, 工厂类可以隐藏复杂性 对象创建(比如如何解析Double 一个字符串)。如果你想改变细节 创建对象,你只需要改变 工厂本身; 你不必每次都改变 构造函数所在代码中的单个位置 调用。
答案 0 :(得分:11)
我实际上认为他们提供的例子不一定是很好的例子。
当您构建类时,Factory模式在.NET中变得更有用。例如,查看WebRequest class。
这个类通常通过调用:
来实例化WebRequest request = WebRequest.Create(url);
WebRequest.Create方法使用Factory模式。根据URL的类型,它将创建WebRequest的不同类型(子类)。例如,如果您传递http://
个网址,则实际上会创建HttpWebRequest个实例 - ftp://
网址会创建FtpWebRequest。
通过在此处使用Factory模式,可以在以后添加更多URL类型而无需更改客户端上的任何代码 - 您只需传入不同的URL(作为字符串),然后获取新对象。
答案 1 :(得分:2)
工厂的整个想法似乎有所不同。这不仅仅是隐藏实现的复杂性,而是关于控制的反转(IoC)。
Sender
和Receiver
个对象,而是让MessageFactory
对象负责创建它们。TcpMessageFactory
(MessageFactory
后代)创建TcpSender
和TcpReceiver
个对象。所以现在我们的应用程序适用于TCP。UdpSender
和UdpReciever
。此外,我们还实施了UdpMessageFactory
(MessageFactory
后代)TcpMessageFactory
或UdpMessageFactory
)并在我们的应用程序中进一步使用它。在此示例中,MessageFactory.CreateSender
和MessageFactory.CreateReciever
必须是抽象方法; Sender
&的方法Reciever
形成他们的公共API(合同)也必须是抽象的。
IDllTypeFactory
IDllTypeXxx
方法时返回CreateXxx
个对象。这些IDllTypeXxx
实际上是由我们最初计划导出的类型实现的。但是如您所知,.NET采用统一的汇编格式,可以在不同模块之间传递对象。而且,反射允许创建一个你根本不知道的类型。因此,很少使用.NET中的工厂。
答案 2 :(得分:1)
工厂模式是我在我的程序中使用最多的模式。在某些情况下它可能非常有用,但使用它时一定要小心。 如果您的工厂看起来像构造函数重载,那么它可能应该是构造函数重载。 MSDN文章给出的示例并不好。事实上,我很久以来一直认为像Int,String等对象不会考虑彼此的重载,因为它们是结构而不是类,并且通常情况下, struct constructors不应该抛出异常(例如,如果你可以将“hello world”提供给int)就会发生异常。但我认为。
当然,网络上有很多地方可以找到更好的解释,说明何时使用工厂模式及其好处。 Reed给出的示例是最好的并遵循我使用Factories的规则:当我有一个类层次结构或许多实现某个接口的类时,我使用工厂,我想构建其中一个对象但是接收一个对象超类/接口而不是对象本身。这样,调用工厂的对象不必担心实现细节。它知道它正在期待一个特定类的对象,即使它是演员也是如此。
在我正在构建的当前应用程序(程序生成器)中,我需要解析数据表SQL定义。我使用家庭酿造解析器来做到这一点。每次解析器遇到变量(“IDENTIFIER VARIABLE-TYPE”)时,我都会调用一个工厂并将字符串传递给它。然后工厂检查变量类型子串并返回 SqlVariable ,实际上可能是 IntegerSqlVariable 或 CharSqlVariable 。
主解析器对象不知道它得到了什么变量。它将SqlVariable推送到列表并读取下一行。当然,我可以有一个类来处理所有变量类型;我个人选择不这样做。
答案 3 :(得分:0)
是的,您可以使用构造函数重载来更改构造函数,而不必更改源代码中的每个区域,但如果您不是非常小心,这将很快导致数量庞大的构造函数。
我认为本文的一般概念是隐藏实现,而不是必须阻止大量构造函数重载以便考虑构造函数的更改。作为对象的想法不应该知道它是如何构建的。
在给出的示例中,您不希望阻塞Int类如何从字符串或double变为int,因此您创建Factory,其唯一的职责是从Y参数创建X对象。
我肯定会建议将Head First Design Patterns一书作为学习设计模式的好介绍。这些示例是基于Java的,但无论您使用何种语言,它们背后的逻辑都适用。