代码之家  ›  专栏  ›  技术社区  ›  Steve

.NET框架中的构造函数与工厂

  •  2
  • Steve  · 技术社区  · 15 年前

    下面是一篇关于.NET框架使用模式的文章。我不确定我是否理解下面摘录中的粗体部分。这是否意味着,如果更改创建对象的详细信息,您(可能)会更改构造函数参数?

    在框架中有很多情况下, 无法获取结构或类的新实例 不需要自己调用它的构造函数。这个 System.Convert类包含一个静态主机 像这样工作的方法。转换整数 例如,对于布尔值,可以调用 convert.toboolean并传入整数。这个 此方法调用的返回值是一个新的布尔值 如果整数非零且 否则为“假”。convert类创建 布尔值正确。其他类型 转换方法的工作原理类似。解析 Int32和Double上的方法返回新实例 将这些对象设置为适当的值 只给了一个字符串。

    创建新对象实例的策略是 被称为工厂模式。而不是调用 对象的构造函数,可以询问对象 工厂为您创建实例。那样, 工厂类可以隐藏 对象创建(例如如何解析 字符串)。如果你想改变 创建对象时,只需更改 工厂本身; 你不必改变每一个 代码中构造函数所在的位置 打电话。

    来自: http://msdn.microsoft.com/en-us/magazine/cc188707.aspx .

    4 回复  |  直到 15 年前
        1
  •  11
  •   Reed Copsey    15 年前

    实际上,我认为他们提供的例子不一定是很好的例子。

    构造类时,工厂模式在.NET中变得更有用。例如,看看 WebRequest class .

    此类通常通过调用以下命令来实例化:

    WebRequest request = WebRequest.Create(url);
    

    这个 WebRequest.Create 方法使用工厂模式。根据URL的类型,它将创建WebRequest的不同类型(子类)。如果你通过了它 http:// 例如,URL,您将实际创建一个 HttpWebRequest 实例-AN ftp:// URL将创建一个 FtpWebRequest .

    通过在这里使用工厂模式,以后可以添加更多的URL类型,而不需要更改客户端上的任何代码——您只需传入不同的URL(作为字符串),并获得一个新的对象。

        2
  •  2
  •   Alex Yakunin    15 年前

    整个工厂的想法似乎不一样。这不仅是为了隐藏实现的复杂性,也是为了控制反转(IOC)。

    • 而不是创造 Sender Receiver 你自己的东西,让我们做 MessageFactory 负责创建它们的对象。
    • 让我们设想一下,最初我们实现了 TcpMessageFactory ( 信息工厂 后代)创造 TcpSender TcpReceiver 物体。所以现在我们的应用程序使用TCP。
    • 稍后,我们发现UDP更快。所以我们实施了 UdpSender UdpReciever . 此外,我们还实施了 UdpMessageFactory ( 信息工厂 后代)
    • 现在我们可以允许用户选择要使用的协议。基于此,我们创建工厂对象(或者 TCP消息工厂 UDP消息工厂 )并在我们的应用中进一步使用。

    在这个例子中 MessageFactory.CreateSender MessageFactory.CreateReciever 必须是抽象方法;方法 发件人 和; Reciever 形成它们的公共API(契约)也必须是抽象的。

    顺便说一下,最初工厂主要用于对象创建:想象C++库(DLL),它必须允许将一组自己的类型创建到Meave.exe。在不同的模块之间传递实例几乎是不可能的,因为它们的结构依赖于特定的编译器。但是可以通过接口。所以这样的DLL应该:

    • 导出返回工厂界面的函数,例如 IDllTypeFactory
    • 实现它的对象必须返回 IDllTypeXxx 调用ITS时的对象 CreateXxx 方法。这些 IDL型 实际上是由我们最初计划导出的类型实现的。

    但正如您所知,.NET具有统一的程序集格式,可以在不同模块之间传递对象。此外,反射允许创建一个根本不知道的类型。所以.NET中的工厂很少使用。

        3
  •  1
  •   Bruno Brant    15 年前

    工厂模式是我在程序中使用最多的模式。在某些情况下,它可能非常有用,但是使用它时一定要小心。 如果您的工厂看起来像一个构造函数重载,那么它可能是一个构造函数重载。 msdn文章中给出的例子并不好。事实上,在相当长的一段时间内,我一直相信in t、string等对象不会考虑彼此的重载,因为它们是 结构体 通常,结构构造函数不应该抛出异常(例如,如果可以将“hello world”馈送给int,则会发生这种情况),而不是类和。但我是这么想的。

    当然,网络周围有很多地方,在那里你可以找到更好的解释何时使用工厂模式及其好处。Reed给出的例子是最好的例子之一,并且遵循我使用工厂的规则:当我有一个类层次结构或一些实现某个接口的类时,我使用工厂,并且我想要构建这些对象中的一个,但是收到一个超类/接口的对象,而不是对象本身。这样,调用工厂的对象 不必担心实现细节 . 它知道它期望某个类的对象,这就是它得到的,即使它是一个强制转换。

    在我正在构建的当前应用程序(程序生成器)中,我需要解析数据表SQL定义。我使用一个家庭BREW解析器来实现这一点。每当解析器遇到一个变量(“标识符变量类型”)时,我调用一个工厂并将字符串传递给它。然后工厂检查变量类型substring并返回给我 SQL变量 ,实际上可能是 整数sqlvariable 或A charsqlvariable(字符变量) .

    主解析器对象不知道它得到了什么变量。它将sqlvariable推送到一个列表并读取下一行。当然,我可以有一个类来处理所有变量类型;我个人选择不这样做。

        4
  •  0
  •   Wysawyg    15 年前

    是的,您可以使用构造函数重载来更改构造函数,而不必更改源代码中的每个区域,但是如果您不小心的话,这将很快导致大量的构造函数。

    我认为本文的一般思想是隐藏实现,而不是为了解释构造函数的更改而必须防止大量的构造函数重载。作为对象的想法不应该知道如何构造它。

    在给出的示例中,您不希望用如何从字符串或double中变成in t类来阻塞in t类,因此您创建的工厂的唯一职责是从y参数创建x对象。

    我肯定会建议头一设计模式书作为学习设计模式的一个很好的入门。这些例子是基于Java的,但它们背后的逻辑,不管你使用什么语言。

    推荐文章