我应该将一个应用范围内的对象传递给需要它的对象,还是应该使用单例
本文关键字:对象 单例 一个 我应该 范围内 应用 | 更新日期: 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对象的中介,使应用程序的各个部分使用起来更简单。
任何本质上有限的资源都是通过单例访问的好选择。
我更喜欢使用单例方法,因为您总是只需要一个实例。