设计模式之单例模式(控制台方法)
介绍
单例模式是软件工程中最着名的模式之一。从本质上讲,单例是一个只允许创建自身的单个实例的类,并且通常可以简单地访问该实例。最常见的是,单例不允许在创建实例时指定任何参数——否则对实例的第二个请求但具有不同的参数可能会有问题!(如果对于具有相同参数的所有请求都应访问相同的实例,则工厂模式更合适。)本文仅处理不需要参数的情况。通常,单例的要求是它们是懒惰地创建的——即直到第一次需要时才创建实例。 具体介绍请看另一个博主的博客,转载于 https://www.cnblogs.com/leolion/p/10241822.html
我在这里介绍的是饿汉模式,创建两个类,一个是普通的类,一个是单例类
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace Day12 8 { 9 class Student1 10 { 11 //第一步:构造函数私有化,这样就不能用new进行实例 12 private Student1() { } 13 //第二步:自行创建一个实例,采用static代表一个实例 14 private static Student1 student1 = new Student1();//饿汉模式 15 //第三步:提供外界能访问的方法 16 public static Student1 Getstudent1() 17 { 18 return student1; 19 } 20 public string Name { get; set; } 21 public void Show() 22 { 23 Console.WriteLine("HELLO!" + Name); 24 } 25 } 26 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace Day12 8 { 9 public class Student 10 { 11 public string Name { get; set; } 12 public void Show() 13 { 14 Console.WriteLine("HELLO!"+Name); 15 } 16 } 17 }
然后在控制台上输出,调用要进行输出的方法和要赋值的字段名称
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace Day12 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 //Student st = new Student(); 14 //st.Name = "王鹏泽"; 15 //st.Show(); 16 Student1 st = Student1.Getstudent1(); 17 st.Name = "jack"; 18 st.Show(); 19 Student1 st1 = Student1.Getstudent1(); 20 st1.Show(); 21 Console.ReadLine(); 22 } 23 } 24 }
懒汉模式,
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace Day12 8 { 9 class Student1 10 { 11 //第一步:构造函数私有化,这样就不能用new进行实例 12 private Student1() { } 13 //第二步:自行创建一个实例,采用static代表一个实例 14 private static Student1 student1 =null;//初始化为null为懒汉模式 15 //第三步:提供外界能访问的方法 16 public static Student1 Getstudent1() 17 { 18 if (student1==null) 19 { 20 student1 = new Student1(); 21 } 22 return student1; 23 } 24 public string Name { get; set; } 25 public void Show() 26 { 27 Console.WriteLine("HELLO!" + Name); 28 } 29 } 30 }
两种模式的对比:
在多线程下 ,懒汉模式 ,不加锁是非常不安全的
饿汉模式是因为提前调用时,就进行了 实例化操作,所以多线程下 相对较安全
/// 适用于在多线程的情况下保证只有一个实例化对象的情况
双重验证模式:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace Day12 8 { 9 class Student1 10 { 11 //定义一个线程锁资源 12 private static readonly Object obj = new object(); 13 //第一步:构造函数私有化,这样就不能用new进行实例 14 private Student1() { } 15 //第二步:自行创建一个实例,采用static代表一个实例 16 private static Student1 student1 =null;//初始化为null为懒汉模式 17 //第三步:提供外界能访问的方法 18 public static Student1 Getstudent1() 19 { 20 // 外部不能实例化对象,但是能调用类里面的静态方法 21 // 外部需要调用这个方法来使用类对象,如果对象不存在就创建 22 // 这里面使用两个判断是否为null的原因是,我们不需要每次都对实例化的语句进 23 //行加锁,只有当对象不存在的时候加锁就可以了 24 //第一重验证 25 if (student1==null) 26 { 27 // 锁定的作用就是为了保证当多线程同时执行这句代码的时候保证对象的唯一性 28 // 锁定会让同时执行这段代码的线程排队执行 29 // lock里面需要用一个已经存在的对象来判断,所以不能使用myInstance 30 lock (obj) 31 { 32 // 这里还需要一个判断的原因是,如果多线程都通过了外层的判断进行排队 33 // 那将会实例化多个对象出来,所以这里还需要进行一次判断,保证线程安全 34 //第二重验证 35 if (student1==null) 36 { 37 student1 = new Student1(); 38 } 39 } 40 41 } 42 return student1; 43 } 44 public string Name { get; set; } 45 public void Show() 46 { 47 Console.WriteLine("HELLO!" + Name); 48 } 49 } 50 } 51
越是无知的人越是觉得自己无所不知(之前的自己)
越是学习的人越是觉得自己会的太少了(现在的自己)
共勉