良好的构造函数设计

本文关键字:构造函数 | 更新日期: 2023-09-27 18:35:20

一般来说,在构造函数中构造其他对象是一个坏主意(我通常不喜欢它)? 假设类型 A 的对象需要类型 B 的实例。 类型 B 的实例应该是静态的,因为我真的只想要它的一个副本......真。。。不,说真的。 类型 b 还会引发类型 A 需要处理的事件。 类型 B 在我无法控制的外部库中。 使我的 B 型对象静态似乎在测试中很烦人。 我最初想让 A 完全静态,因为它本质上是 B 的代理。 也许这才是真正的问题。 当作为代理的对象需要初始化时,什么是好的代理设计?我至少可以想到三个选项:

  1. 传入参数需要构造类型 A 和类型 B。 然后,类型 A 的构造函数构造类型 B.(调用 create 方法以从构造函数中返回类型 B 将是相同的基本概念。
  2. 传入构造对象。
  3. 创建初始化方法。

我不喜欢选项 1,因为它很复杂。 我将不得不执行各种B型初始化代码,设置事件处理程序等。我不喜欢选项 2,因为我不想让外界知道这种依赖关系。 类 A 是唯一将与类 B 交互的类型。一般来说,我不喜欢初始化方法,或者"保护"封装依赖项状态的方法。 我似乎最终得到了很多这样的代码:

if (typeB != null && typeB.State != Unitialized)

呸。

这是我正在使用的一些示例代码。 只是在寻找如何使它真正干净,简单且易于维护。

public class A
    {
        private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        private B b;
        public new A(string productName, string serviceName)
        {
            b = new B
            {
                ProductName = productName,
                ServiceName = serviceName
            };
            b.SomethingHappened += b_HandleIt;

更新:我在评论中引用了这篇务实的文章来回答。 我熟悉 DI、IoC、工厂方法、生成器模式、构造函数注入、方法注入、属性注入、测试驱动设计等。 我想我的问题是,我如何在简单性和良好的设计之间取得平衡,同时根据我当前的需求尽可能少地和尽可能快地编码? B类永远不会被取代,除了A类之外,我没有理由相信除了A类之外的任何东西都会在我的项目中使用B类。 我有点担心测试的接缝,但 A 类非常简单,代码很少,基本上包装了一个第三方类。

良好的构造函数设计

最终使用构建器注入进行 DI。 不是绝对激动,但这似乎是最直接的方法。

如果你真的只需要一个 b 类型的实例,那么你为什么要把它作为 A 构造的一部分来处理呢?它应该是类 B 的类成员,你可以在需要时从类 B 获取它。类 A 的实例不需要自己的指向 b 的指针(而且它有自己的 b 实例是没有意义的,因为只有一个实例。