设计模式之单例模式(一)

设计模式之单例模式(创建型设计模式)

先说一段废话记录一下生活吧

  又是一年毕业季,临近毕业,最近当然是在忙毕业设计了,今天查重报告下来了,查重率百分之二十八点多,要求百分之二十,真他妈shit了,加上天气炎热,最近很是烦躁,心情像一坨屎,每天上午死在宿舍,下午去篮球场,不过还有nba可以看,最近几场东西部决赛看的真是心脏不太好,昨天骑士和凯子抢七,老詹是真牛批,一个人扛着一个队硬是拿下了比赛,今天火箭和勇士抢七,本来想看我火在主场将西部决赛冠军收入囊中,但是没有保罗的火箭就是不太稳啊,喜欢登哥但是有时候总是掉链子,尤其今天的火箭27中0,我他么更是shit了.怎么说呢,明年接着来吧.

  最近不知道看些什么,写些什么,还是写写设计模式吧,之前看过一些设计模式,没有记录下来,这次写一下整理整理吧.

========================================================================

单例模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

简单来说,我的对象由我自己来创建(单例当然只创建一个对象了),但是我可以给你们使用.

注意:

  • 1、单例类只能有一个实例。
  • 2、单例类必须自己创建自己的唯一实例。
  • 3、单例类必须给所有其他对象提供这一实例。

主要解决:一个全局使用的类频繁地创建与销毁。

何时使用:当您想控制实例数目,节省系统资源的时候。

优点: 1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如首页页面缓存)。

            2、避免对资源的多重占用(比如写文件操作)。

缺点:没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。

使用场景: 1、要求生产唯一序列号。

      2、WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。

      3、创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。

然后我们来看一下单例模式的类图,如下图所示:

简单的说一下吧:

1.首先我们要有一个私有的构造方法,这样就能满足这个对象只能由我们自己创建的这个条件了

2.然后呢,我们提供一个私有的变量,用来存放这个唯一的实例

3.提供一个方法,返回这个唯一的实例(当然我们要进行一下判断了)

接下来我们可以简单的写一个单例类

namespace Singleton
{
    /// <summary>
    /// 这是单例类
    /// </summary>
    public class Unique
    {
        //提供一个变量来存储唯一的实例
        private static  Unique uniqueInstance;
        //提供一个私有的构造器
        private  Unique() { }
        //提供一个方法供其他类进行调用
        public static Unique GetUniqueInstance() {
            if (uniqueInstance == null) {
                uniqueInstance = new Singleton.Unique();
            }
            return uniqueInstance;
        }
        public void Show() {
            Console.WriteLine("单例中的方法");
        }
    }
}
单例类
namespace Singleton
{
    class Program
    {
        static void Main(string[] args)
        {
            Unique unique = Unique.GetUniqueInstance();
            unique.Show();
            Console.ReadKey();
        }
    }
}
主程序

  写到这,是不是觉得很简单呢,当然了,因为我们是单线程的程序,所以不会出现问题.

  那我们考虑一下多线程的情况,假如现在有两个线程,其中一个线程执行到了GetUniqueInstance()方法,判断等于空,接着会去创建单例对象,这时第二个线程也来了,同样也执行到了GetUniqueInstance().但是呢,这时第一个线程还没有将对象创建出来(new一个对象哪有那么容易,当然是需要时间的了,就像你找女朋友一样),所以判断也为空,接着也去创建这个单例对象,这种情况是不是就创建了两个单例对象呢,这当然是错的,违背了我们只创建一个对象的初衷,所以我们要解决多线程的问题.

================================以下多线程=========================================

  菜鸟教程上介绍了6种创建单例模式的方式,其中一种是不能保证线程安全的,也就是和我们上边写的类似,其余5种分别是:1 懒汉式线程安全,2 饿汉式,3 双检锁/双重校验锁,4 登记式/静态内部类,5 枚举

下面我先简单介绍一下饿汉式

饿汉式,就是一个饥饿的汉子(此处一个猥琐的表情),也就是在单例类内部的变量直接去把对象创建出来,而不是在GetUniqueInstance()中给这个变量赋值,(这个过程实在java类加载时初始化,对应的.net是哪个步骤我还不太清除,希望大神看到这能够指点迷津,给我留言哦)是CLR吗,底层我还没研究过...

下面我们来改造一下

 

 public class Unique
    {
        //提供一个变量来存储唯一的实例
        private static Unique uniqueInstance = new Unique ();
        //提供一个私有的构造器
        private Unique() { }
        //提供一个方法供其他类进行调用
        public static Unique GetUniqueInstance()
        {
            return uniqueInstance;
        }
        public void Show()
        {
            Console.WriteLine("单例中的方法");
        }
    }
单例类

 

这就改造好了,很简单的,尝试一下

 

 接着看一下双检锁/双重校验锁吧

//双层判断 中间加锁
    public class Unique
    {
        //提供一个变量来存储唯一的实例
        private static Unique uniqueInstance;
        //标识对象 可以锁这个对象
        private static readonly object obj = new object();
        //提供一个私有的构造器
        private Unique() { }
        //提供一个方法供其他类进行调用
        public static Unique GetUniqueInstance()
        {
            if (uniqueInstance == null) { //没有这层判断也可以,但是每次都是先锁对象,再去判断,加锁解锁耗时间,所以有这层判断更好
                lock (obj) {
                    if (uniqueInstance == null) {
                        uniqueInstance = new Unique();
                    }
                }
            }
            return uniqueInstance;
        }
        public void Show()
        {
            Console.WriteLine("单例中的方法");
        }
    }
单例类

之前一直认为这个双重锁就是懒汉模式,因为他比较懒,使用的时候才去创建,java中的懒汉模式使用到了synchronized关键字,也就是同步方法.C#中同步方法我还没想起来是哪个关键字,唉,才疏学浅,菜的一批,大家就自行百度吧

 写到这也差不多了,剩下还有几种就不写了,有点饿,该去吃晚饭了

当然了,最后一句,欢迎指正,欢迎留言,欢迎转载(转载最好把我的博客地址贴上)

 

posted @ 2018-05-29 18:37  zkh-balance  阅读(168)  评论(0编辑  收藏  举报