1、单例模式可以解决的问题
1.1 为了节约系统资源,避免不必要的重复;
1.2 多个实例对象会存在冲突;
以上两个原因大多数情况下是同时存在的,最常见的例子就是Windows操作系统里的任务管理器、系统信息等。
2、单例模式Sample
2.1 以下我们以Windows的任务管理器为例进行说明(源于http://blog.csdn.net/lovelion/article/details/7420883 刘伟老师):
using System;
namespace TaskMan
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("tm01 = getInstance()");
TaskManager tm01 = TaskManager.getInstance();
Console.WriteLine("tm02 = getInstance()");
TaskManager tm02 = TaskManager.getInstance();
Console.Write("tm01 == tm02 ? =");
Console.Write( tm01 ==tm02);
Console.ReadLine();
}
}
class TaskManager
{
/// <summary>
/// 定义私有静态的类型
/// </summary>
private static TaskManager tm = null;
/// <summary>
/// 构造函数私有声明,外部不可访问
/// </summary>
private TaskManager()
{
//初始化任务管理器
}
public void disProcesses()
{
//显示进程
}
public void disServices()
{
//显示服务
}
/// <summary>
/// 第一次调用getInstance()方法时将创建唯一实例,
/// 再次调用时将返回第一次创建的实例,从而确保实例对象的唯一性。
/// </summary>
/// <returns></returns>
public static TaskManager getInstance()
{
if (tm == null)
{
tm = new TaskManager();
}
return tm;
}
}
}
该代码的输出结果为:
可以看出这两个实例是相同的。
分析以上代码,我们为了实现class的实例的唯一性,主要通过以下几个步骤:
(1) 禁止 类 的构造函数对外部的可见,这样,在类的外部,无法使用new 的形式实例化该类;
private TaskManager()
{
//初始化任务管理器
}
(2) 增加一个对外可见的静态方法(public static),将实例化操作封装到该方法中(工厂方法模式);
public static TaskManager getInstance()
{
if (tm == null)
{
tm = new TaskManager();
}
return tm;
}
(3) 为了控制实例的唯一性,我们需要声明一个私有的静态变量,作为实例的载体,每次调用静态方法的时候,我们首先判断该实例是否为null,如果为null,则返回一个new 实例,如果不为null,则返回该实例本身。
private static TaskManager tm = null;
这里 tm 声明为静态变量,每次实例化时不会动态改变tm的值,造成多个实例的存在。
综上所述,单例模式(Singleton Pattern)可以描述为:
- 保证类只能被实例化一次,通过工厂方法自行实例化并向整个系统提供这个实例。
- 这种类也叫做单例类,它向系统提供全局访问的实例化方法。
- 单例模式是一种对象创建型模式。
单例模式的三个基本要素如下:
- 类只能有一个实例;
- 类必须自行创建这个实例;
- 类必须自行向整个系统提供这个实例。
单例模式结构图如下:
2.2 服务器负载均衡器Sample
using System;
using System.Collections.Generic;
using System.Text;
namespace LoadBalan
{
class Program
{
public static object CodePagesEncodingProvider { get; private set; }
static void Main(string[] args)
{
//解决Core .net 控制台中文乱码输出问题
Console.OutputEncoding = Encoding.UTF8;
//创建四个均衡器对象
LoadBalancer balancer01;
LoadBalancer balancer02;
LoadBalancer balancer03;
LoadBalancer balancer04;
balancer01 = LoadBalancer.getInstance();
balancer02 = LoadBalancer.getInstance();
balancer03 = LoadBalancer.getInstance();
balancer04 = LoadBalancer.getInstance();
if(balancer01==balancer02 && balancer01 == balancer03 && balancer01 == balancer04)
{
Console.WriteLine("负载均衡器具有唯一性");
}
Console.ReadLine();
}
}
/// <summary>
/// 负载均衡器
/// </summary>
class LoadBalancer
{
/// <summary>
/// 私有静态成员,唯一实例的载体
/// </summary>
private static LoadBalancer _instance = null;
/// <summary>
/// 服务器列表
/// </summary>
private List<string> _serverList = null;
/// <summary>
/// 私有的构造函数
/// </summary>
private LoadBalancer()
{
//初始化服务器列表
_serverList = new List<string>();
//......
}
/// <summary>
/// 公有静态成员方法,返回唯一实例
/// </summary>
/// <returns></returns>
public static LoadBalancer getInstance()
{
if (_instance == null)
{
_instance = new LoadBalancer();
}
return _instance;
}
/// <summary>
/// 添加一个服务器
/// </summary>
/// <param name="server"></param>
public void addServer(string server)
{
_serverList.Add(server);
}
/// <summary>
/// 删除一个服务器
/// </summary>
/// <param name="server"></param>
public void removeServer(string server)
{
_serverList.Remove(server);
}
/// <summary>
/// 随机获取一个服务器
/// </summary>
/// <returns></returns>
public string getServer()
{
Random random = new Random();
int i = random.Next(_serverList.Count);
return _serverList[i];
}
}
}
运行结果:
下节继续学习饿汉模式和懒汉模式