首先,让我们看一下单例模式是怎样的。
public sealed class Singleton { private static Singleton instance = null; private static readonly object padlock = new object(); Singleton() { } public static Singleton Instance { get { if (instance == null) { lock (padlock) { if (instance == null) { instance = new Singleton(); } } } return instance; } } }
这是<<C# in Depth>>这本书中提供的标准代码。
实现单例模式的思路是:
- 定义一个密封类(sealed)以避免其它类继承此类(据书中所说此举虽然不是必要的,但可以帮助JIT进行更多优化)。
- 定义并初始化该类自身的静态实例(instance)为null,用该instance来检测控制在创建单例模式的类的程序中只有一个该类的实例。
- 定义并初始化一个只读(readonly)的用于锁(lock)的object对象以满足多线程环境。
- 创建一个只有get方法的该类的静态变量,用于创建该类的实例。
- 最后在该类的构造函数中写入相关代码。
可以看到整个过程中并未传入参数。
考虑以下问题:
如果我用单例模式连接并查询数据库单个表的所有信息,但数据库中有很多表,我想往单例模式中传入参数怎么办?
看以下代码:
public sealed class Database { private static Database _instance = null; private static readonly object _Object = new object(); private string conString = "connection string"; private Database(string tableName, DataTable dt) { using (SqlConnection Conn = new SqlConnection(conString)) { Conn.Open(); string sql = "select * from " tableName; using (SqlCommand cmd = new SqlCommand(sql)) { using (SqlDataAdapter da = new SqlDataAdapter()) { cmd.CommandType = CommandType.Text; cmd.Connection = Conn; da.SelectCommand = cmd; da.Fill(dt); } } } } public static Database GetInstance(string tableName, DataTable dt) { if (_instance == null) { lock (_Object) { if (_instance == null) { _instance = new Database(tableName, dt); } } } return _instance; } }
DataTable dt = new DataTable(); Database.GetInstance("MyTable",dt); Database.GetInstance("MyTable2", dt); dataGridView1.DataSource = dt;
由于单例模式,DataGridView中将只显示‘MyTable’的信息。
问题虽然得到解决,但单例模式通常提供对该实例的简单访问,是否使用工厂模式会有更合适呢?
待续...