我应该将一个应用范围内的对象传递给需要它的对象,还是应该使用单例

本文关键字:对象 单例 一个 我应该 范围内 应用 | 更新日期: 2023-09-27 18:05:27

在我的具体情况下,我通过嵌套的视图控制器传递一个"facebook"对象(即MonoTouch.FacebookConnect.Facebook的实例),它为项目添加了一个体面的代码。在AppDelegate中实例化之后,总是有一个对象的实例,并且它在应用程序中的大多数视图控制器中使用。所有使用facebook对象的视图控制器在开始时都有这样的内容:

public class MyViewController : UIViewController
{
    Facebook facebook;
    public MyViewController (Facebook facebook)
    {
        this.facebook = facebook;
    }
    // ...
}

…除了顶层视图控制器,对象在那里被实例化。

也有一个场景,它被传递"通过"一个嵌套的视图控制器,只是为了让它到一个更深嵌套的视图控制器,利用它。

我知道单例通常是不受欢迎的,它违背了面向对象的原则。我希望代码易于维护。我是否采用了正确的方法,或者单例是否可以在不影响代码质量的情况下完成任务?

我应该将一个应用范围内的对象传递给需要它的对象,还是应该使用单例

我会不惜一切代价避免Singleton。您的方法鼓励松耦合,并允许您通过模拟对象来增加可测试性(如果您将其从具体实现转换过来)。它通常会增加更多的代码,但您的应用程序应该具有更好的可测试性。这允许您使用IoC容器并利用依赖注入。在网上和StackOverflow上有很多关于这类话题的文章和帖子。

也许你的单例是这样的:

public class MyViewController : UIViewController
{
    public MyViewController ()
    {
    }
    public void Foo()
    {
        FaceBookSingleton.Instance.DoSomeAction();
        FaceBookSingleton.Instance.Something = 4;
    }
}

你们是如何围绕Foo()进行测试的?如果你引入了一个突破性的改变,你怎么能更快地知道呢?你怎么知道你的依赖关系图是什么样的呢?像这样测试代码比较困难。不要指望人们浏览你的代码库,试图找出他们是否破坏了什么。通过编写可测试的代码来帮助他们和你自己。

现在看看这样的东西:

public interface ISocialMediaWidget
{
    ISocialMediaWidgetResponse DoSomeUnitOfWork();
}

public class ConcreteSocialMediaWidgetService
{
    protected readonly ISocialMediaWidget socialMediaWidget;
    public ConcreteSocialMediaWidgetService(ISocialMediaWidget widget)
    {
        this.socialMediaWidget = widget;
    }
    public ISocialMediaWidgetResponse Foo()
    {
        return socialMediaWidget.DoUnitOfWork();
    }
}

围绕上述内容编写测试要容易得多。您还可以模拟来自每个接口的响应,以创建各种测试。

public void SocialMediaWidgetTest()
{   //pseudo code
    var testService = new MockObject(ConcreteSocialMediaWidgetService(MockObject_of_ISocialMediaWidget));
    Assert.Equals(someImplementation_of_ISocialMediaWidgetResponse, testService.Foo());
}

首先,单例模式在很大程度上只是其他完全可以接受的OO策略(如"工厂"和记忆)的替代语法。

这是一个语法问题,以及每个语法在你的组织中意味着什么。如果您这样做,是否意味着您的组织可能会对产品MyClass.Current做一些工作?

public class MyClass
{
  public static MyClass Current
  {
    get
    {
      if (SomeSortOfCache['MyClass.Current'] == null) {
        // do something to get populate it.
      }
      return SomeSortOfCache['MyClass.Current'];
    }
  }
}

或者,您的组织更喜欢这样的内容:

public class MyClass
{
  public static MyClass GetCurrent()
  {
    if (SomeSortOfCache['MyClass.Current'] == null) {
      // do something to get populate it.
    }
    return SomeSortOfCache['MyClass.Current'];
  }
}

或者,如果你想把它想象成一个工厂,调用BuildMyClass()CreateMyClass()方法。在幕后,机制基本上是相同的。这主要是你的组织对每种语法和命名约定所做的假设问题。

其次,您已经确定您只希望或只需要允许存在一个实例。因此,我建议使用一种模式,以最少的代码,优雅地促进这一点。

在这种情况下,单例似乎是一个更好的解决方案,因为您可以消除大量重复的代码,并在快速构建应用程序时增加更改的灵活性。

单例还可以充当Facebook对象的中介,使应用程序的各个部分使用起来更简单。

任何本质上有限的资源都是通过单例访问的好选择。

我更喜欢使用单例方法,因为您总是只需要一个实例。