设计模式
我主要侧重理解,毕竟经验太少,而又需要理解。所以这篇博文仅作为自己消化已有的知识用。
单例模式
单例模式,从字面上理解就是这个类我要一个而且也只允许一个产生。这是我一开始的理解。那么我在学习面向对象的过程中,知道的产生类的方式为:类名 实例引用名称=new 类名(参数);
那么,现在问题来了,既然要全局都只允许有且只有一个类的实例,怎么办呢?没有任何专业知识的前提下,我们都知道“节流”。就是不要让这个类“随意”产生实例。而这个想法的技术实现是怎样的呢?我们不妨慢慢来。
先看一下类是怎么生成实例的(我目前基础差,必须这么干。。。。。。)。使用类类型生成该类的实例其实就是一句话:使用new关键字来分配对象【1】。那么,深入一点new关键字是怎么进行类的实例的产生的?使用new关键字后,首先分配内存,然后调用类的构造函数进行实例的初始化。也就是说,创建类的根本操作是调用了类的构造函数。所以说,防止利用new生成类的实例就是防止类的构造函数被调用。
class ExampleClass
{
private ExampleClass()
{
/*构造函数的内容*/
}
}
那么,紧接着就会有另外一个问题:连构造函数都被干掉了(不能通过new自动调用),那我们怎么生成这个类的实例(毕竟我们讨论的是单例,还得有一个实例,否则这个类不就没用了么。。。。)呢?
这个时候,我们可以使用静态方法。为什么是静态?因为在生成这个类之前,这个类只有定义没有实例,只能用静态方法跟类中的内容进行“联通”。而有了这个联通的桥梁,我们也就可以在new不能访问构造函数的前提下,访问到private的构造函数。原因是,静态函数把执行上下文(自己的理解,也许不对。意会)带入到了类内(或者说是定义范围内,我不是很清楚。。。),而这个时候,构造函数的private对内部已经不管用了(嘿嘿,机智啊),这个时候就可以使用(私有)构造函数了(同样是通过new关键字)。这个时候代码大概是这样的
class ExampleClass
{
private ExampleClass()
{
/*构造函数的内容*/
}
public static CreateInstance()
{
ExampleClass instanceRef = new ExampleClass();
/*剩下的操作*/
}
}
但是,这个时候又跳出来一个问题:上述代码中通过public的静态函数“解锁”了私有构造函数,那么不就又等于构造函数可以任意使用了吗(可以随意的new然后返回该实例的引用)?解决这个问题的思路其实很简单,就是设定一个等效的flag位,用来指示到底这个类有没有被创建过。这里使用指向该类的引用类型变量,如果这个变量为null,说明这个类从来没有实例被创建过;反之,就代表已经创建过实例,不应该再执行new ExampleClass()了。此时,代码如下
class ExampleClass
{
/*增加的标志位*/
private static ExampleClass uniqueRef;
private ExampleClass()
{
/*构造函数的内容*/
}
public static ExampleClass CreateInstance()
{
if( uniqueRef == null )
{
/*说明并没有生成过类的实例*/
ExampleClass instanceRef = new ExampleClass();
}
/*剩下的操作*/
return uniqueRef;
}
}
我自己在反复看这个代码的时候有个问题:为什么标志位uniqueRef要为private和static的?我的理解为:static有两种解释:首先如果不是static的话,根本就无法在静态方法CreateInstance()中赋值,其次在道理上也确实应该是static的,因为这个实例是这个类的唯一实例(这个实例的引用是伴随类的);private其实可以为public,不过这时候这个变量会有两种可能:空和非空。不过如果这样,在使用的时候需要判断,增加了不必要的书写麻烦。而将这个访问属性改为private后,将这个判断放在CreateInstance()中则使整体代码更加简洁。
最后,注意这个代码是线程不安全的,但是多线程的知识我还不会,慢慢积累吧。。。