singletonclassDesign Patterns: Singleton Basics 设计模式:单例基础

废话就不多说了,开始。。。

    Design Patterns are among the bread and butter of the good developer's cookbook. Basically, any serious job interview you will have as a Junior to Mid-level programmer, will have a question on Design Patterns in it. They are very important in many regards and essential in others. But to me at least, one has stood above all of the others and that is the Singleton Design Pattern.

    设计模式是全部开辟者平常开辟不可缺少的内容(原文:bread and butter,不可缺少,平常必备). 基本上,口试的时候,由初级到中级的程序员都会遇到关于设计模式的问题。对于开辟而言,设计模式非常重要。但是对于我来说,设计模式中我会列出的第一条就是单例模式(Singleton Design Pattern).

    

    Very rarely have I seen a project that has no implementation of this whatsoever. In this article, I will explain the importance of using this Design Pattern and how to implement it.

    在我所看到的项目中,很少有没有实现单例模式的。这篇文章中,我会想你解释单例模式的重要性以及怎么样实现单例。

    

    

Singleton单例

    那么什么是单例呢?单例答应我们严格控制类有且仅有一个实例化对象在整个程序运行的生命周期内。简略来说,就是在整个程序中都可以访问到这个单例对象,不须要创立新的实例对象。

    

    So what is really the Singleton? Well, it is a Design Pattern that allows us to restrict the class that implements it to have just one instance of itself at all times. In plain terms this means that if we implement Singleton on a class, it will always have just one instance. That's it. That instance will be accessible throughout your code but you will no longer be able to create new instances of the class.

    

    

Why should we use it?为什么要使用单例?

    

有许多使用单例的场景和原因,上面列出一些使用的原因:

    

  1. 你创立的类中须要一个单一封装的模块使你不须要转变代码逻辑的作用域范围就能够动态地做出转变。
  2. 代码中利用单例可以清晰地管理资源。
  3. 减少实例对象个数,单例模式让我们可以更省力地在运行时使用已经封装在类中的方法或者成员。

    

    There are many reasons. Here is a short list of some “why we should do it” stuff:

    

    

  • You will have one singular encapsulation module for the logic of your class that will serve in a way that you can do easy dynamic changes without changing the scope of your programming logic.
  • You can manage a single resource clearly through your code.
  • As the Singleton Design Pattern implements the lazy instantiation, it allows us to get and use it's encapsulated logic as it is needed at runtime.

    

    

When do we need Singleton 为什么我们须要单例?

    项目中须要实现实例的地方时要保证实现的分歧性和通用性。例如游戏中主屏幕分数板上显示玩家的分数,整个游戏休会中都须要的,不管它分数增长到多少如何变化,最后你还是须要用它来统计玩家品级以及计算最高得分等等。对于此,实现一个scoreboard类的单例就非常幻想。分数增长,就会存在就会保存在scoreboard类的单例对象中,这样随时在程序中须要计算得分的时候,我们就能够省力的调用。

    An implementation of Singleton is needed on classes that would represent something that you use in one form and consistently throughout your project. That would be per say your in-game's scoreboard that monitors your current point count. It's something that you would need during your gameplay experience to increment your score. However, you would need it at the end of your level to calculate your high-score. In that regard, implementing Singleton to your scoreboard class would be perfect. You increment your score and it is stored in the single scoreboard object that you have. When the time comes for us to calculate your in-game high score, we simply access this object and see what you've accumulated.

    

    

    另外一个经典的场景是保存和进入棋盘游戏的规则。平日,如果你开辟的是一个一般的棋盘游戏,你的规则可能游戏过程当中都是分歧的。每次游戏回合你都不须要从新为此创立一个新的rule类对象,无论从性能角度还是数据丢失方面去斟酌,都不须要。

    Another classic case would be to store and access the rules of a board game. Normally, if you are developing a regular board game, your rules should be the same all together. There is absolutely no reason for you to create a new object every time and for every game you play. There is no point to have this both from a performance standpoint and from data loss perspective.

    

    

    

But why use Singleton and not a class with static methods?

    

为什么不能用类的静态方法来代替单例模式?

    

    单例不能替代一个定义静态方法的类,两者是完整不同的, 使用的情形也不同。

    Singleton is not a replacement for a class with static methods. It's a totally different thing. It's also used in different cases.

    

    

    你可以使用一个类的静态方法的情况下,你不须要在全部实例。畸形情况下,静态方法是将要使用的操纵对象是类的外部。一般来说,静态方法应该在一个更通用的方法来实现。他们极可能会使用多个逻辑段完整不同的参数。对于单例模式,你有一个类,应该像一个畸形的任务。就是这样。爱好在上面的例子中,它不是仅仅是一类包含一些方法,将要被作为工具使用稍后。它要包含自身的编程逻辑。

    You would use a class with static methods in situations where you do not need an instance at all. Normally, the static methods are going to be used to do operations with objects that are outside of the class. Generally, the static methods should be implemented in a more generic way as well. They are probably going to be used by multiple logic segments with different parameters altogether. With Singleton, you have a class that should work like a normal one. That's it. Like in the examples above, it's not merely a class containing some methods that are going to be used as tools later on. It is going to contain programming logic on its own.

    所要讲的例子 - 你须要在你的棋盘游戏的规则和单例,在你的游戏中的记分牌。您将须要一个静态类,如果你想临时的动态创立可重用UI元素,不属于你的核心接口。

    

    So to talk in examples – you will need Singleton in your board game’s rules and in your in-game scoreboard. You would need a static class if you plan to dynamically instantiate reusable UI elements that serve only temporary purpose and are not a part of your core interface.

    

    

    

    

Singleton Implementations 单例实现

    

    Here we will take a look at a real implementation of Singleton in Java. 

    

    Java单例模式实现:

    

    

public class Scoreboard {

	public int currentScore; //we will use this for the score later on
	private static Scoreboard singleton = null; //this we will need for the implementation
	
	protected Scoreboard(){
		//nothing here really. At least for this example.
	}

	public static Scoreboard instance(){
		//this is the method that we are going to use to return the one instance of this class.
		if(singleton == null){
			singleton = new Scoreboard();
		}
		
		return singleton;
	}

}

    

    Now to use this implementation in another class in order for you to see how it's actually going to happen.

    

    

public class HelloScoreboard{
	public static void main(String[] args){
		Scoreboard.instance().currentScore = 10; //here we call and set ÃÃÃÃÃÃÃÃâcurrentScoreÃÃÃÃÃÃÃÃâ
		System.out.println(Scoreboard.instance().currentScore.toString());
	}
}

    

    如上面的例子,我们在定义的单例类Scoreboard中, 定义了instance()方法。通过这个方法,我们可以获得一个该类的实例对象。任何对这个类的调用都必须通过那个方法。当初,如果我们看一下currentScore变量,我们互看到在HelloScoreboard的主方法中我们设置的value是10,根据这一点,每次我们引用这个变量的时候,这个值都是10,至少我们转变它的时候,这个值才会转变。

    As seen in the example above, we have the Singleton class Scoreboard. It has its instance() method. Through this method we will get the one instance of this class. Any calls we want to make to the class have to be done through this method. Now, if we take a look at the currentScore variable, we will see that in the main method of HelloScoreboard we are setting it to the value of 10. From this point on, every time we refer to this variable, its value is going to be 10, at least until we change it for some reason. Again, its value can be changed wherever we please.

    

    

    每日一道理
人的生命似洪水奔流,不遇着岛屿和暗礁,难以激起美丽的浪花。

    

Singleton Issues 单例问题

    实现单例模式也必须注意一些问题,如果没有准确的处置,你可能会遇到更多的问题。

    

    There are some major issues with the Singleton Design Pattern to look out for. If not implemented correctly and in turn, not handled correctly, you may be getting more issues then you would wish.

    

    

    

Multithreading 多线程

    

    这多是单例模式会遇到一个最大的问题之一。问题大致可以描述成这样:你有两个线程都须要调用我们单例的对象,由于是独立的两个线程,我们会获得一个逻辑悖论(logical paradox) - 单例对象的两个实例化对象。我们可真的不想遇到这样的问题,我们只想实现一个实例化封装这个单例对象的资源和功能。对于多线程的问题,我们尽量避免使用单例模式。

    This is quite possibly one of the biggest issues out there. The problem here is something like this - let's say that you have two threads that for some reason are calling our Singleton object. Since they are two separate threads, we would get a logical paradox - two instances of the Singleton object. That's just not what we want at all. What we want is to have one instance that encapsulates a singular resource and functionality. By having the multithread issue, we completely make the point of the Singleton useless.

    

    

    如何“处理”这个问题?或许说“修正”这个问题,我们可以对单例对象进行同步/锁的操纵。

    Well, generally this is not a problem that can be truly "fixed". It can merely be "mended". We can do that by synchronising/locking the Singleton object.

    

    

    Here is a Java implementation for this:

    

    

public class Scoreboard {

	public int currentScore; //we will use this for the score later on
	private static Scoreboard singleton = null; //this we will need for the implementation
	
	protected Scoreboard(){
		//nothing here really. At least for this example.
	}

	public static Scoreboard instance(){
		//this is the method that we are going to use to return the one instance of this class.
		if(singleton == null){
            synchronized(Scoreboard.class) {
                if(singleton == null){
					singleton = new Scoreboard();
                }
            }
		}
		
		return singleton;
	}

}

    

    So this is what basically is happening here - on entry, the first thread will check if the singleton instance is 

    

    null

    

    . If it is, then we go to the synchronized lock. When the other thread enters, the creation of the instance is locked. At this point we have another failsafe as well. If/when the second thread manages to get past the lock, when the first thread is done, we have a new check. At this point we block out the issue with the multiple instances.

    

    

    

Unit Testing 单元测试

    


    这是另外一个主要单例问题。这是因为我们须要测试Singleton实例,每一个类,使用它在一个这样或那样的。这只是没有单元测试的想法。我们要测试的只有一件事 - 没有一件事和单例。这使得两件事情,这也使得corrupt 测试。这里要注意的是另外一件事Singleton对象的事实,有一种“状态”。在任何时候,你想转变什么,你转变单例的价值,这样的 - 它的当前状态。这使得它几乎不可能跟踪状态和大批的测试案例中的测试数据。

    This is another major Singleton issue. That's because we would need to test the Singleton instance with every single class that uses it in one way or another. That's just not the idea of the Unit Tests. We want to test just one thing - not one thing and the Singleton. That makes two things and it also makes a corrupt test. Another thing to note here is the fact that the Singleton object has a "state" of a sort. At any time you change something, you change the Singleton's values and thus - it's current state. That makes it near impossible to track the states and the test data in a massive test case.

    

    

    

Debugging and Solving Issues

    

    Since the Singleton can be called at any one point in your code, this makes it really hard to track when your instance got it's values/logics messed up beyond expectations.

    

    

    The resolution here should really be to be careful why, when and where you call your Singleton object but mostly - you need to watch out if your implementation of this pattern is really needed. If you are making too many calls to the Singleton object, you might want to consider another approach.

    

    

    

The Singleton "knows" Too Much

    

    Some times, the deviation of the Sinleton pattern from the traditional OOP understanding is making it an issue of what kind of things it can manipulate. We should not put calculations or any process that has a major role in our code. That's to say that if you have some basic and driving logic, you should by all means NOT include any parts of it inside the Singleton implementation.

    

    

    

Dependency Issues

    

    This is a real blocker as well. When we use the Singleton Design Pattern, we take the risk of making the code too dependent on the object's state/values/logic. Let's say we expect the Singleton object to behave in a certain fashion. We base our logic on that behavior and we think that things are going to go smooth. And it does. Everything is going ok and you are happy that your code works as expected. Well, that's up until you totally forget what you've done with this. And then you decide to make some minor changes here and there. Now, your Singleton object does not behave the way you thought it would. Not only that, now you are totally not in controll of what's happening.

    

    

    

Interesting Points

    

    I chose Java for the examples in the previous chapter because I find it to be really easily portable to other programming languages. If you are doing work with C++ or C# you should have no problem in porting this code. I myself use C# more often then Java nowadays and in C# I prefer to use a property instead of an 

    

    instance()

    

     method as this is visible by the name I gave it in the example above. Normally, the general consensus between the Java developers, especially in the Enterprise industry, is that the convention for this method is 

    

    getInstance()

    

    . It does not matter how you are going to call it really. I prefer it to be short and I find it fitting for this example.

    

    

    

    

Conclusion

    

    Using Design Patterns in your code is really something from which you can benefit a lot. Singleton is quite possibly the most common of them all along side with the 

    Factory Design Pattern

    .

    

    

    Knowing how to implement Singleton can serve you really well.

    转载自:http://www.gamedev.net/page/resources/_/technical/game-programming/design-patterns-singleton-basics-r3132

    本文中的全部译文仅用于学习和交流目的,转载请务必注明出处和本文链接

文章结束给大家分享下程序员的一些笑话语录: Bphone之你们聊,我先走了!移动说:我在phone前加o,我叫o缝;苹果说:我在phone前i,我是i缝;微软说:我在phone前加w,我叫w缝;三星说:你们聊,我先走了!
将来王建宙写回忆录的时候,一定要有一句“常小兵为中国移动的发展做出了不可磨灭的贡献”。

--------------------------------- 原创文章 By
singleton和class
---------------------------------

原文地址:https://www.cnblogs.com/xinyuyuanm/p/3098182.html