当前位置:  开发笔记 > 编程语言 > 正文

GOF Singleton模式有没有可行的替代方案?

如何解决《GOFSingleton模式有没有可行的替代方案?》经验,为你挑选了5个好方法。

面对现实吧.Singleton模式是高度争议与成群程序员话题围栏边.有些人认为,辛格尔顿只不过是一个美化的全球变量,而其他人则以模式发誓并不断使用它.但是,我不希望单身人士的争议成为我问题的核心. 每个人都可以进行一场拔河比赛并与之抗争,看看谁能为我所关心的所有人赢得胜利.我想说的是,我不相信有一个正确的答案,我不是故意尝试激烈的党派争吵.当我问这个问题时,我只对单身替代品感兴趣:

他们是GOF Singleton模式的任何特定替代品吗?

例如,很多次我在过去使用单例模式时,我只想保留一个或多个变量的状态/值.但是,变量的状态/值可以使用静态变量而不是使用单例模式在类的每个实例化之间保留.

还有什么其他的想法?

编辑: 我真的不希望这是另一篇关于"如何正确使用单身人士"的帖子.再一次,我正在寻找避免它的方法.为了好玩,好吗?我想我在你最好的电影预告片中问一个纯粹的学术问题,"在一个没有单身的平行宇宙中,我们能做什么?"



1> Rasmus Faber..:

要了解解决单身人士的正确方法,你需要了解单身人士(以及一般的全球状态)有什么问题:

单身人士隐藏了依赖关系.

为什么这很重要?

因为如果隐藏依赖关系,则往往会忽略耦合量.

你可能会争辩

void purchaseLaptop(String creditCardNumber, int price){
  CreditCardProcessor.getInstance().debit(creditCardNumber, amount);
  Cart.getInstance().addLaptop();
}

比...更简单

void purchaseLaptop(CreditCardProcessor creditCardProcessor, Cart cart, 
                    String creditCardNumber, int price){
  creditCardProcessor.debit(creditCardNumber, amount);
  cart.addLaptop();
}

但至少第二个API清楚地表明了该方法的协作者是什么.

因此,解决方法Singletons的方法不是使用静态变量或服务定位器,而是将Singleton类更改为实例,这些实例在它们有意义的范围中实例化并注入到需要它们的组件和方法中.您可以使用IoC框架来处理此问题,或者您可以手动执行此操作,但重要的是摆脱全局状态并使依赖关系和协作显式化.


在一个成熟的多层应用程序中,第二种方法通常会产生大量不必要的代码.通过用逻辑来污染中间层的代码以进入较低层,在该层次上不需要的对象,我们不是在创建不需要的依赖项吗?假设导航堆栈中的第4层启动后台操作,如文件上载.现在假设您想要在用户完成时提醒用户,但到那时,用户可能处于应用程序的完全不同的部分,该部分仅与初始视图共享第1层.大量不需要的代码......
此外,发布/发布或观察者模式也可能与"失去耦合跟踪"一样糟糕,因为任何必须通过严重依赖于它们的框架进行调试的人都会证明这一点.至少对于单例,调用的方法名称与调用代码位于同一个位置:)就个人而言,我认为所有这些策略都有它们的位置,没有一个可以盲目实现.邋co的编码员会使意大利面条脱离任何模式,而负责任的编码人员不必为了创造优雅的代码而过度依赖意识形态限制.

2> Jacek Szymań..:

Alex Miller在" 我讨厌的模式 "中引用了以下内容:

"当单身人士看起来像是答案时,我发现它通常更明智:

    创建单例的界面和默认实现

    在系统的"顶部"构建默认实现的单个实例.这可能是在Spring配置中,也可能在代码中,或者以各种方式定义,具体取决于您的系统.

    将单个实例传递到需要它的每个组件(依赖注入)


我知道这已经快5岁了,但你能扩展一下吗?我想我被告知创建单身的正确方法是使用界面.如果我正在做的事情是'好',并且没有像我被告知的那么可怕,我会感兴趣.

3> 小智..:

我遇到的最好的解决方案是使用工厂模式来构造类的实例.使用该模式,可以确保在使用它的对象之间只共享一个类的实例.

虽然管理起来会很复杂,但在阅读了这篇博客文章"所有单身人士去哪里了?"之后.,看起来很自然.另外,它可以帮助您隔离单元测试.

总之,你需要做什么?每当一个对象依赖于另一个对象时,它将仅通过其构造函数(在您的类中没有新的关键字)接收它的实例.

class NeedyClass {

    private ExSingletonClass exSingleton;

    public NeedyClass(ExSingletonClass exSingleton){
        this.exSingleton = exSingleton;
    }

    // Here goes some code that uses the exSingleton object
}

然后,工厂.

class FactoryOfNeedy {

    private ExSingletonClass exSingleton;

    public FactoryOfNeedy() {
        this.exSingleton = new ExSingletonClass();
    }

    public NeedyClass buildNeedy() {
        return new NeedyClass(this.exSingleton);
    }
}

由于您只将实例化一次工厂,因此将会有一个exSingleton实例化.每次调用buildNeedy时,NeedyClass的新实例都将与exSingleton捆绑在一起.

我希望这有帮助.请指出任何错误.


Julien是对的,这个修复有一个根本的缺陷,就是你隐含地说你只能实例化一个工厂.如果你采取必要的预防措施,以确保只有一个工厂被实例化(朱利安所说),你最终会......一个单身人士!实际上,这种方法只是在单例之上添加了一个不必要的抽象层.
确保只有在需要私有构造函数并将buildNeedy方法定义为静态方法时才会实例化Factory.

4> Thomas Owens..:

你不应该为了避免任何模式而竭尽所能.模式的使用既可以是设计决策,也可以是自然拟合(它只是落实到位).在设计系统时,您可以选择使用模式或不使用模式.但是,你不应该忘记任何最终是设计选择的东西.

我没有避免使用Singleton模式.它是适当的,我使用它或它是不合适的,我不使用它.我相信它就这么简单.

Singleton的适当性(或缺乏)取决于具体情况.这是必须做出的设计决策,必须理解(并记录)该决定的后果.


如果适当或不合适,请在答案中说说.好的请.

5> 小智..:

Spring或任何其他IoC-Container在这方面做得相当不错.由于类是在app本身之外创建和管理的,因此容器可以创建简单的类单例并在需要的地方注入它们.

推荐阅读
mobiledu2402851323
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有