面对现实吧.Singleton模式是高度争议与成群程序员话题都围栏边.有些人认为,辛格尔顿只不过是一个美化的全球变量,而其他人则以模式发誓并不断使用它.但是,我不希望单身人士的争议成为我问题的核心. 每个人都可以进行一场拔河比赛并与之抗争,看看谁能为我所关心的所有人赢得胜利.我想说的是,我不相信有一个正确的答案,我不是故意尝试激烈的党派争吵.当我问这个问题时,我只对单身替代品感兴趣:
他们是GOF Singleton模式的任何特定替代品吗?
例如,很多次我在过去使用单例模式时,我只想保留一个或多个变量的状态/值.但是,变量的状态/值可以使用静态变量而不是使用单例模式在类的每个实例化之间保留.
还有什么其他的想法?
编辑: 我真的不希望这是另一篇关于"如何正确使用单身人士"的帖子.再一次,我正在寻找避免它的方法.为了好玩,好吗?我想我在你最好的电影预告片中问一个纯粹的学术问题,"在一个没有单身的平行宇宙中,我们能做什么?"
要了解解决单身人士的正确方法,你需要了解单身人士(以及一般的全球状态)有什么问题:
单身人士隐藏了依赖关系.
为什么这很重要?
因为如果隐藏依赖关系,则往往会忽略耦合量.
你可能会争辩
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框架来处理此问题,或者您可以手动执行此操作,但重要的是摆脱全局状态并使依赖关系和协作显式化.
Alex Miller在" 我讨厌的模式 "中引用了以下内容:
"当单身人士看起来像是答案时,我发现它通常更明智:
创建单例的界面和默认实现
在系统的"顶部"构建默认实现的单个实例.这可能是在Spring配置中,也可能在代码中,或者以各种方式定义,具体取决于您的系统.
将单个实例传递到需要它的每个组件(依赖注入)
我遇到的最好的解决方案是使用工厂模式来构造类的实例.使用该模式,可以确保在使用它的对象之间只共享一个类的实例.
虽然管理起来会很复杂,但在阅读了这篇博客文章"所有单身人士去哪里了?"之后.,看起来很自然.另外,它可以帮助您隔离单元测试.
总之,你需要做什么?每当一个对象依赖于另一个对象时,它将仅通过其构造函数(在您的类中没有新的关键字)接收它的实例.
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捆绑在一起.
我希望这有帮助.请指出任何错误.
你不应该为了避免任何模式而竭尽所能.模式的使用既可以是设计决策,也可以是自然拟合(它只是落实到位).在设计系统时,您可以选择使用模式或不使用模式.但是,你不应该忘记任何最终是设计选择的东西.
我没有避免使用Singleton模式.它是适当的,我使用它或它是不合适的,我不使用它.我相信它就这么简单.
Singleton的适当性(或缺乏)取决于具体情况.这是必须做出的设计决策,必须理解(并记录)该决定的后果.
Spring或任何其他IoC-Container在这方面做得相当不错.由于类是在app本身之外创建和管理的,因此容器可以创建简单的类单例并在需要的地方注入它们.