3

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

public class MyViewController : UIViewController
{
    Facebook facebook;

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

...除了顶层视图控制器,对象被实例化。

还有一种情况是它“通过”嵌套视图控制器,只是为了将它传递给使用它的更深层嵌套的视图控制器。

我知道单例通常不受欢迎,并且违反了 OOP 原则。我希望代码易于维护。我是否采取了正确的方法,或者单身人士会在不影响代码质量的情况下做到这一点?

4

4 回答 4

6

I would avoid the Singleton at all costs. Your approach encourages loose-coupling and allows you to increase your testability by mocking out the object (if you converted it from your concrete implementation). It generally adds more code but you should have better testability in your application. That allows you to use an IoC container and utilize Dependency Injection. There are many great articles and posts on the web and here on StackOverflow about such topics.

Perhaps your singleton might look like this:

public class MyViewController : UIViewController
{
    public MyViewController ()
    {
    }

    public void Foo()
    {
        FaceBookSingleton.Instance.DoSomeAction();
        FaceBookSingleton.Instance.Something = 4;
    }
}

How do you do your testing around Foo()? How would you know, sooner, if you introduced a breaking change? How do you know what your dependency graph looks like? It's harder to test code like this. Don't count on people browsing your code base to try and figure out if they broke something. Help them out and yourself out by writing code that can be tested.

Now maybe look at something as such:

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();
    }
}

Writing tests around the aforementioned is much easier. You can also mock out the response from each interface to create all kinds of tests.

public void SocialMediaWidgetTest()
{   //pseudo code
    var testService = new MockObject(ConcreteSocialMediaWidgetService(MockObject_of_ISocialMediaWidget));
    Assert.Equals(someImplementation_of_ISocialMediaWidgetResponse, testService.Foo());
}
于 2013-03-22T20:01:30.063 回答
2

首先,单例在很大程度上只是其他完全可接受的 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'];
  }
}

Or, if you want to think of it as a factory, call the method BuildMyClass() or CreateMyClass(). Under the hood, the mechanisms are largely the same. It primarily a question of assumptions your organization makes about each syntax + naming convention.

Secondly, you've established that you only want or need to allow one instance of to exist. So, I'd suggest using a pattern that facilitates this gracefully, with the least amount of code.

于 2013-03-22T19:57:15.453 回答
2

In this case, a singleton would seem to be a better solution as you would eliminate a lot of repetitive code, and increase flexibility for changes as you quickly build out your application.

A singleton could also act as an intermediary to the Facebook object, making it simpler for various parts of your application to use.

Any resource that is limited in nature is a good candidate for accessing through a singleton.

于 2013-03-22T20:01:57.863 回答
0

I can prefer to use singleton approach as you need always only one instance.

于 2013-03-22T19:59:42.800 回答