问题描述
让我们面对现实吧. Singleton模式为高度争议与hordes programers on 围栏的两侧.有些人觉得单身人士不仅仅是一个荣耀的全球变量,而其他人则不断地发誓并不断使用它.我不想要 singleton condredsondorporsy 但是,我的问题. 每个人都可以进行拔河比赛,并与之抗争,看看谁赢得了我关心的一切.我想说的是,我不相信有一个正确的答案,也不是故意尝试煽动党派争吵.当我问一个问题时,我只是对 singleton-anternatives 感兴趣:
他们是Gof单例模式的任何特定选择吗?
例如,很多时候我过去都使用了单例模式,我只是有兴趣保留一个或几个变量的状态/值.但是,可以使用 static变量而不是使用单例模式在类的每个实例化之间保留变量的状态/值.
您还有什么其他想法?
编辑:我真的不希望这是关于"如何正确使用单例"的另一篇文章.同样,我正在寻找避免它的方法.娱乐,好吗?我想我在您最好的电影预告片中问一个纯粹的学术问题:"在没有单身人士的平行宇宙中,我们能做什么?"
推荐答案
Alex Miller在" 我讨厌"引用以下内容:
"当单身人士看起来像答案时,我发现它通常更明智:
- 创建一个界面和单身顿的默认实现
- 在系统的"顶部"上构建默认实现的单个实例.这可能是在弹簧配置中,或在代码中,或根据您的系统来定义的.
- 将单个实例传递到需要它的每个组件(依赖项注入)
其他推荐答案
要了解解决方法的正确方法,您需要了解单身人士(以及一般全球状态)的错误:
:单例隐藏依赖.
为什么这很重要?
因为如果隐藏了依赖项,则倾向于失去耦合量的跟踪.
您可能会说
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明确了该方法的合作者是什么.
因此,解决单身人士的方法是不使用静态变量或服务 - 位数,而是将单身式级别更改为实例,这些实例是在它们具有意义的范围中实例化的,并注入了需要它们的组件和方法.您可能会使用IOC-FRAMEWORK来处理此问题,也可以手动进行操作,但重要的是要摆脱您的全球状态并明确使依赖关系和协作.
其他推荐答案
我遇到的最好的解决方案是使用工厂模式来构建您的课程实例.使用该模式,您可以保证 只有一个类的实例在使用它的对象之间共享.
i虽然管理会很复杂,但是阅读此博客文章"所有单身人士都在哪里?" ,看起来很自然.顺便说一句,它有助于隔离单元测试.
总而言之,您需要做什么?每当一个对象取决于另一个对象时,它将仅通过其构造函数接收一个实例(您的类中没有新关键字).
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时,Newsecter的新实例都会与Exsingleton捆绑在一起.
我希望这会有所帮助.请指出任何错误.
问题描述
Let's face it. The Singleton Pattern is highly controversial topic with hordes programmers on both sides of the fence. There are those who feel like the Singleton is nothing more then a glorified global variable, and others who swear by pattern and use it incessantly. I don't want the Singleton Controversy to lie at the heart of my question, however. Everyone can have a tug-of-war and battle it out and see who wins for all I care. What I'm trying to say is, I don't believe there is a single correct answer and I'm not intentionally trying inflame partisan bickering. I am simply interested in singleton-alternatives when I ask the question:
Are their any specific alternatives to the GOF Singleton Pattern?
For example, many times when I have used the singleton pattern in the past, I am simply interested in preserving the state/values of one or several variables. The state/values of variables, however, can be preserved between each instantiation of the class using static variables instead of using the singleton pattern.
What other idea's do you have?
EDIT: I don't really want this to be another post about "how to use the singleton correctly." Again, I'm looking for ways to avoid it. For fun, ok? I guess I'm asking a purely academic question in your best movie trailer voice, "In a parallel universe where there is no singleton, what could we do?"
推荐答案
Alex Miller in "Patterns I Hate" quotes the following:
"When a singleton seems like the answer, I find it is often wiser to:
- Create an interface and a default implementation of your singleton
- Construct a single instance of your default implementation at the “top” of your system. This might be in a Spring config, or in code, or defined in a variety of ways depending on your system.
- Pass the single instance into each component that needs it (dependency injection)
其他推荐答案
To understand the proper way to workaround Singletons, you need to understand what is wrong with Singletons (and global state in general):
Singletons hide dependencies.
Why is that important?
Because If you hide the dependencies you tend to lose track of the amount of coupling.
You might argue that
void purchaseLaptop(String creditCardNumber, int price){ CreditCardProcessor.getInstance().debit(creditCardNumber, amount); Cart.getInstance().addLaptop(); }
is simpler than
void purchaseLaptop(CreditCardProcessor creditCardProcessor, Cart cart, String creditCardNumber, int price){ creditCardProcessor.debit(creditCardNumber, amount); cart.addLaptop(); }
but at least the second API makes it clear exactly what the method's collaborators are.
So the way to workaround Singletons is not to use static variables or service-locators, but to change the Singleton-classes into instances, which are instantiated in the scope where they make sense and injected into the components and methods that need them. You might use a IoC-framework to handle this, or you might do it manually, but the important thing is to get rid of your global state and make the dependencies and collaborations explicit.
其他推荐答案
The finest solution I have came across is using the factory pattern to construct instances of your classes. Using the pattern, you can assure that there is only one instance of a class that is shared among the objects that use it.
I though it would be complicated to manage, but after reading this blog post "Where Have All the Singletons Gone?", it seems so natural. And as an aside, it helps a lot with isolating your unit tests.
In summary, what you need to do? Whenever an object depends on another, it will receive an instance of it only through its constructor (no new keyword in your class).
class NeedyClass { private ExSingletonClass exSingleton; public NeedyClass(ExSingletonClass exSingleton){ this.exSingleton = exSingleton; } // Here goes some code that uses the exSingleton object }
And then, the factory.
class FactoryOfNeedy { private ExSingletonClass exSingleton; public FactoryOfNeedy() { this.exSingleton = new ExSingletonClass(); } public NeedyClass buildNeedy() { return new NeedyClass(this.exSingleton); } }
As you will instantiate your factory only once, there will be a single instantiation of exSingleton. Every time you call buildNeedy, the new instance of NeedyClass will be bundled with exSingleton.
I hope this helps. Please point out any mistakes.