物由心生

再努力一点儿
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

设计模式学习笔记(二) 单例模式 1

Posted on 2017-07-06 15:37  物由心生  阅读(179)  评论(0)    收藏  举报

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];
        }
    }
}

 运行结果:

 

 下节继续学习饿汉模式和懒汉模式