设计模式学习第二天:设计模式总结——1单例模式

原文博主:http://blog.csdn.net/zhaoguiqun/article/details/6026763

一、 单例(Singleton)模式
      单例模式的特点:
• 单例类只能有一个实例。 
• 单例类必须自己创建自己的唯一实例。 
• 单例类必须给所有其它对象提供这一实例。

单例模式应用:
每台计算机可以有若干个打印机,但只能有一个Printer Spooler,避免两个打印作业同时输出到打印机。 
一个具有自动编号主键的表可以有多个用户同时使用,但数据库中只能有一个地方分配下一个主键编号。否则会出现主键重复。

二、 Singleton模式的结构:
 
      Singleton模式包含的角色只有一个,就是Singleton。Singleton拥有一个私有构造函数,确保用户无法通过new直接实例它。除此之外,该模式中包含一个静态私有成员变量instance与静态公有方法Instance()。Instance方法负责检验并实例化自己,然后存储在静态成员变量中,以确保只有一个实例被创建。

三、 在什么情形下使用单例模式:
      使用Singleton模式有一个必要条件:在一个系统要求一个类只有一个实例时才应当使用单例模式。反过来,如果一个类可以有几个实例共存,就不要使用单例模式。

注意:
     不要使用单例模式存取全局变量。这违背了单例模式的用意,最好放到对应类的静态成员中。
     不要将数据库连接做成单例,因为一个系统可能会与数据库有多个连接,并且在有连接池的情况下,应当尽可能及时释放连接。Singleton模式由于使用静态成员存储类实例,所以可能会造成资源无法及时释放,带来问题。

四、 C#中的Singleton模式
     C#的独特语言特性决定了C#拥有实现Singleton模式的独特方法。这里不再赘述原因,给出几个结果:
方法一:
下面是利用.NET Framework平台优势实现Singleton模式的代码:
sealed class Singleton
{
    private Singleton();
    public static readonly Singleton Instance=new Singleton();
 }

这使得代码减少了许多,同时也解决了线程问题带来的性能上损失。那么它又是怎样工作的呢?
注意到,Singleton类被声明为sealed,以此保证它自己不会被继承,其次没有了Instance的方法,将原来_instance成员变量变成public readonly,并在声明时被初始化。通过这些改变,我们确实得到了Singleton的模式,原因是在JIT的处理过程中,如果类中的static属性被任何方法使用时,.NET Framework将对这个属性进行初始化,于是在初始化Instance属性的同时Singleton类实例得以创建和装载。而私有的构造函数和readonly(只读)保证了Singleton不会被再次实例化,这正是Singleton设计模式的意图。
(摘自:http://www.cnblogs.com/huqingyu/archive/2004/07/09/22721.aspx )
不过这也带来了一些问题,比如无法继承,实例在程序一运行就被初始化,无法实现延迟初始化等。
详细情况可以参考微软MSDN文章:《Exploring the Singleton Design Pattern》

方法二:
     既然方法一存在问题,我们还有其它办法。
public sealed class Singleton
{
   Singleton() { }
   public static Singleton GetInstance()
   {
      return Nested.instance;
   }
  
   class Nested
   {
       // Explicit static constructor to tell C# compiler
       // not to mark type as beforefieldinit
       static Nested()
       {
       }
       internal static readonly Singleton instance = new Singleton();
   }

}
     这实现了延迟初始化,并具有很多优势,当然也存在一些缺点。详细内容请访问:《Implementing the Singleton Pattern in C#》。文章包含五种Singleton实现,就模式、线程、效率、延迟初始化等很多方面进行了详细论述。

五、代码示例

实例1:

using System;

namespace Singleton
{
    public class Singleton
    {
        private static Singleton instance;

protected Singleton()
        {
        }

public static Singleton Instance()
        {
            if (instance == null)
                instance = new Singleton();

return instance;
        }
    }

public class Client
    {
        public static void Main(string[] args)
        {
            Singleton singleton1 = Singleton.Instance();
            Singleton singleton2 = Singleton.Instance();

if (singleton1 == singleton2)
            {
                Console.WriteLine("The same singleton.");
            }

if (singleton1.Equals(singleton2))
                Console.WriteLine("Point to the same memorySpace.");

Console.ReadLine();
        }
    }
}

实例2:

/*下面这段Singleton代码演示了负载均衡对象。在负载均衡模型中,有多台服务器可提供服务,
 * 任务分配器随机挑选一台服务器提供服务,以确保任务均衡(实际情况比这个复杂的多)。
 * 这里,任务分配实例只能有一个,负责挑选服务器并分配任务。
 */
using System;
using System.Collections;
using System.Threading;

namespace Singleton
{
    public class LoadBalancer
    {
        private static LoadBalancer balancer;
        private ArrayList servers = new ArrayList();
        private Random random = new Random();

private LoadBalancer()
        {
            servers.Add("ServerI");
            servers.Add("ServerII");
            servers.Add("ServerIII");
            servers.Add("ServerIV");
            servers.Add("ServerV");
        }

public static LoadBalancer GetLoadBalancer()
        {
            // Support multithreaded applications through
            // "Double checked locking" pattern which avoids 
            // locking every time the method is invoked
            if (balancer == null)
            {
                Mutex mutex = new Mutex();
                mutex.WaitOne();
                if (balancer == null)
                    balancer = new LoadBalancer();

mutex.Close();
            }

return balancer;
        }

public string Server
        {
            //Simple, but effective random load balancer
            get
            {
                int num = random.Next(servers.Count);
                return servers[num].ToString();
            }
        }
    }

public class SingletonApp
    {
        public static void Main(string[] args)
        {
            LoadBalancer b1 = LoadBalancer.GetLoadBalancer();
            LoadBalancer b2 = LoadBalancer.GetLoadBalancer();
            LoadBalancer b3 = LoadBalancer.GetLoadBalancer();
            LoadBalancer b4 = LoadBalancer.GetLoadBalancer();

//Same instance?
            if ((b1 == b2) && (b2 == b3) && (b3 == b4) && (b4 == b1))
                Console.WriteLine("Same Instance.");

// Do the load balancing
            Console.WriteLine(b1.Server);
            Console.WriteLine(b2.Server);
            Console.WriteLine(b3.Server);
            Console.WriteLine(b4.Server);

Console.ReadLine();
        }
    }
}

时间: 2024-08-06 02:51:50

设计模式学习第二天:设计模式总结——1单例模式的相关文章

设计模式学习总结:(10)单例模式探讨

单例模式(Singleton)很简单,从名字也很容易知道解决的是唯一对象创建问题,很多时候,如果因为一个对象只需要存在一份,正常对象创建方式有种杀鸡用牛刀的感觉.同时,也不能假设用户素质足够高,至少我们要保证从语法上,多个对象存在是不合理的,我们所要做的,就是约束对方的行为. 意图: 保证一个类仅有一个实例,并提供一个全局访问点. 在c++中为了限定对象的创建,我们需要把构造函数设置为私有,保证无法从外界构造,同时需要一个静态变量指针来保存唯一对象,最后至少还需要一个函数来获得这个唯一对象. c

设计模式学习之---模板方法设计模式

在我们的日常生活中,模板方法是应用的很广的,我们身边有很多模板方法的身影,举个很高大上的例子就是我们的奥运会的开幕仪式:奥委会对于不同国家举办奥运会开幕式提供的步骤都是一样的: 1.升国旗,奏国歌 2.奥委会人发言 3.文艺汇演 4.奥运运动员入场仪式 5.点燃火炬 但是,对于不同的国家,他们的内容肯定是不一样的,这就是一种模板方法.那么,我们在java的实现中,应该是怎么进行表现呢? 这里再用一个例子来演示,我们的饮料机,一个饮料机可以制作咖啡和茶: 那么我们先定义一个制作饮料的抽象基类: p

Java设计模式学习记录-桥接模式

前言 这次介绍结构型设计模式中的第二种模式,桥接模式. 使用桥接模式的目的就是为了解耦,松散的耦合更利于扩展,但是会增加相应的代码量和设计难度. 桥接模式 桥接模式是为了将抽象化与实现化解耦,让二者可以独立地变化.方便对每一部分的扩展,以及单独的维护.抽象化的一方与实现化的一方之间建立一个桥梁,这样两者的依赖关系就可以通过这个桥梁来建立了. 举例 三个小动物要过河,分别是小猪,小鸡,小马,小猪要去河对面的空地晒太阳,小鸡要去河对面的小树林里找虫子吃,小马要去河对面的草地里吃草.那么它们三个都要经

Java设计模式学习记录-装饰模式

前言 装饰模式也是一种结构型模式,主要是目的是相对于类与类之间的继承关系来说,使用装饰模式可以降低耦合度.JDK中有不少地方都使用到了装饰模式,例如Java的各种I/O流,javax.swing包中一些图形界面构件功能的增强等地方都运用了装饰模式. 装饰模式 定义 装饰模式的定义是:在不改变原类文件以及不使用继承的情况下,动态的扩展一个对象的功能.装饰模式是通过创建一个包装对象来实现的,也就是用装饰来包裹真实的对象. 举例 还是老规矩,举例说明,在给亲朋好友过生日时会买生日蛋糕,然后生日蛋糕又有

Java设计模式学习记录-迭代器模式

前言 这次要介绍的是迭代器模式,也是一种行为模式.我现在觉得写博客有点应付了,前阵子一天一篇,感觉这样其实有点没理解透彻就写下来了,而且写完后自己也没有多看几遍,上次在面试的时候被问到java中的I/O的各种实现用到了什么设计模式,我愣是想半天没想出来了,人家还给提示了我也没想出来,最后还是面试官给出的答案,是装饰模式,听到答案后就恍然大悟了,前两天刚看了装饰模式,还写下了I/O操作中的各种类都是用到了装饰模式,后来想想两方面原因造成的当时没回答出来,一是面试时紧张就容易想不起来,二是对设计模式

Java设计模式学习记录-状态模式

前言 状态模式是一种行为模式,用于解决系统中复杂的对象状态转换以及各个状态下的封装等问题.状态模式是将一个对象的状态从该对象中分离出来,封装到专门的状态类中,使得对象的状态可以灵活多变.这样在客户端使用时无需关心对象的状态,可以实现自身的一致性处理.最近工作有些忙,更新博客慢了.还是要严格要求自己的,抽时间也要坚持学习. 状态模式 概念介绍 状态模式允许一个对象在其状态改变时,改变它的行为,对象看起来似乎修改了它的类. 想要在改变自身状态时改变对象行为,最直接的方法就是在代码中将所有可能发生的情

Java设计模式学习笔记,一:单例模式

开始学习Java的设计模式,因为做了很多年C语言,所以语言基础的学习很快,但是面向过程向面向对象的编程思想的转变还是需要耗费很多的代码量的.所有希望通过设计模式的学习,能更深入的学习. 把学习过程中的笔记,记录下来,只记干货. 第一部分:单例模式的内容 单例模式:类只能有一个实例. 类的特点:1.私有构造器:2.内部构造实例对象:3.对外提供获取唯一实例的public方法. 常见的单例模式实现有五种形式: 1.饿汉式. 2.懒汉式. 3.双重检查锁式. 4.静态内部类式. 5.枚举式. 以下分别

java/android 设计模式学习笔记(一)---单例模式

前段时间公司一些同事在讨论单例模式(我是最渣的一个,都插不上嘴 T__T ),这个模式使用的频率很高,也可能是很多人最熟悉的设计模式,当然单例模式也算是最简单的设计模式之一吧,简单归简单,但是在实际使用的时候也会有一些坑. PS:对技术感兴趣的同鞋加群544645972一起交流 设计模式总目录 java/android 设计模式学习笔记目录 特点 确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例. 单例模式的使用很广泛,比如:线程池(threadpool).缓存(cache).对

设计模式学习01—单例模式

一.动机与定义 系统中有些资源只能有一个,或者一个就够,多个浪费.例如一个系统只能有一个窗口管理器或文件系统.一个系统只能有一个计时器或序号生成器.web系统只能有一个页面计数器等等.此时,最好就需要把这些资源设置成有且仅有一个实例. 代码中也就是如何保证一个类只有一个实例并且这个实例能够被访问呢?只有一个实例的就意味着不能让其他类来实例化,也就是只能自己实例化自己.能够被访问也就意味着自身要对外提供全局方法来获取到这个实例,这就是单例模式. 单例模式定义:确保某一个类只有一个实例,而且自行实例