实现一个只能实例化一个对象的类(C#)
收听我的腾讯微博吧http://t.qq.com/wuhanbiao收听我的新浪微博吧http://t.sina.com.cn/hanbiaowu
上次峰哥出了一个思考题:实现一个只能实例化一个对象的类(C#)。
峰哥言:去写一个只能实例化一个对象的类。就像有些程序只能打开一个,打开第二个的时候,会跳出原来那个或是提示程序在运行?>*&……%
我想:
第一个想到的是static,静态存储持续。在C/C++里面,静态持续变量按链接性可分为三种,即外部链接性、内部链接性和无链接性。此处讨论无链接性的静态持续变量,即用static限定符在代码块中定义的局部变量。此变量的特点是,静态存储,虽然变量只在定义它的代码块可用,但它在该代码块不处于活动状态的时候仍然存在于内存之中。因此在两次函数调用之间,静态局部变量的值将保持不变。另外,如果初始化了静态局部变量(只能用常量初始),则程序只在启动时进行一次初始化,之后的函数调用将不会像自动变量(auto)那样再次被初始化。
但是峰哥的提示强调的是将构造函数设为私有的(private)。我想不通,到底该如何处理?
既然构造函数是私有的,那就肯定不能直接通过构造函数来生成对象,而应该用一个公有的(public)成员函数来调用构造函数,而对象都还没有又想要调用成员函数,那么此函数必定是静态的,即下面的StaticConstruct()。第二个问题,当有人想实例化第二个对象的时候,怎么阻止?……阻止很简单,关键是如何判断是第二次还是第一次,那就需要一个静态成员currentInstance。后来,我觉得答案应该是这样的,至少这是一种可行的方案。
实现代码:
/// Once.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication2011_3_7
{
class Once
{
private string text;
private string name;
private DateTime birthday;
static Once currentInstance = null;
private Once()
{
text = "我只能实例化一个对象哦!";
name = ">_< 我还没有名字呢!";
// 记录当前时间,设为生日
birthday = DateTime.Now;
}
~Once()
{
currentInstance = null;
}
static public Once StaticConstruct()
{
if (null == currentInstance)
{
currentInstance = new Once();
}
else
{
Console.WriteLine("对象已经创建过了哦!");
//return null;
}
//currentInstance = new Once();
return currentInstance;
}
public void ShowMySecret()
{
Console.WriteLine("告诉你一个秘密:" + text);
}
public void SetMyName(string name)
{
this.name = name;
}
public void ShowMyName()
{
Console.WriteLine("我的名字是:" + name);
}
public void ShowMyBirthday()
{
Console.WriteLine("我的生日是:" + birthday.ToLongDateString() + birthday.ToLongTimeString() + " " + birthday.Millisecond + "毫秒");
}
}
}
测试代码:
/// Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication2011_3_7
{
class Program
{
static void Main(string[] args)
{
// 实例化第一个对象
Once instance1 = Once.StaticConstruct();
instance1.SetMyName("TheSoleInstance");
instance1.ShowMySecret();
instance1.ShowMyName();
instance1.ShowMyBirthday();
Console.WriteLine();
// 试图实例化第二个对象
Once instance2 = Once.StaticConstruct();
instance2.ShowMySecret();
instance2.ShowMyName();
instance2.ShowMyBirthday();
Console.WriteLine();
// 改变“第二个对象”的名字,再显示第一个对象的名字
instance2.SetMyName("TheInstance2");
instance1.ShowMyName();
Console.WriteLine();
OutOfMain();
Console.Read();
}
static void OutOfMain()
{
// 试图实例化第三个对象
Once instance3 = Once.StaticConstruct();
instance3.ShowMySecret();
instance3.ShowMyName();
instance3.ShowMyBirthday();
Console.WriteLine();
}
}
}
运行结果:
[img=http://b204.photo.store.qq.com/http_imgload.cgi?/rurl4_b=3a87d52f114bea68769ef6c5be4edfc7d521103c9c4a34bbd5c2a5594c426fb2d9e999707e0c4fd225449b0873588ff6953c9481c421d784f687fe231d8d6c62e7c074eae71b79b4d6e15a86918ca02669c32cab&a=206&b=204][/img]
分析:生日(构造时间)一样,说明这是同一个对象,而且在更改“第二个对象”的名字,而第一个对象的名字也随之改变,说明它们是同一个对象。
若在第二次实例化对象的时候,不返回已有实例的引用,而是返回空,return null。
则效果如下
[img=http://b205.photo.store.qq.com/http_imgload.cgi?/rurl4_b=3a87d52f114bea68769ef6c5be4edfc7689bc75eee54b0e9ac787564e66632841cbde27ee9fbe1b1fc024f3f8e8512a1058fdac521620ad410e9786ea2d1e7307823b07bb011862814f2f170fcad25acd074cf50&a=201&b=205][/img]
为处理的异常。很显然,当instance2为null时,instance2.ShowMySecret();是有问题的。
至此,该类已经实现了一次只能实例化一个对象的功能。
收听我的腾讯微博吧http://t.qq.com/wuhanbiao
收听我的新浪微博吧http://t.sina.com.cn/hanbiaowu --------------------编程问答-------------------- 单件模式,去看看设计模式吧 --------------------编程问答--------------------
--------------------编程问答--------------------
class A
{
private A(){ }
public static Create() { return new A() }
}
+1 --------------------编程问答-------------------- 单件模式,注意单线程还是多线程就好.
补充:.NET技术 , C#