《Head First 设计模式》学习心得
单件模式
定义:确保一个雷只有一个实例,并提供一个全局的访问点。
应用场景:当只需要一个类对象时,比如注册表对象,线程池对象,缓存等。这个时候只需要一个对象。如果有多个对象会造成资源浪费或者访问冲突。
单线程中的单间模式
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace 单件模式
{
class Program
{
static void Main(string[] args)
{
var aa = ChocolateBoiler.GetInstance();
var bb = ChocolateBoiler.GetInstance();
Console.WriteLine(ChocolateBoiler.InstanceCount);
Console.ReadKey();
}
}
public class ChocolateBoiler
{
public bool Empty { get; set; }
public bool Boiled { get; set; }
public static int InstanceCount { get; set; }
private static ChocolateBoiler _uniqueInstance;
static ChocolateBoiler()
{
InstanceCount = 0;
}
// 声明为私有构造器
private ChocolateBoiler()
{
Empty = true;
Boiled = false;
}
// 实例访问通道
public static ChocolateBoiler GetInstance()
{
lock (_locker)
{
if (_uniqueInstance == null)
{
InstanceCount++;
_uniqueInstance = new ChocolateBoiler();
}
return _uniqueInstance;
}
}
}
}
多线程中单件模式:
在多线程中,每个可以同时访问GetInstance()函数,所以会产生多个实例。
解决方法一:利用lock同步对函数的访问,优点是简单,缺点是会降低性能。
该函数对性能影响不大的情况下用该方法。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace 单件模式
{
class Program
{
static void Main(string[] args)
{
ChocolateBoiler chocolateBoiler1;
ChocolateBoiler chocolateBoiler2;
ChocolateBoiler chocolateBoiler3;
Thread t1 = new Thread(() =>
{
Console.WriteLine("线程1");
chocolateBoiler1 = ChocolateBoiler.GetInstance();
});
Thread t2 = new Thread(() =>
{
Console.WriteLine("线程2");
chocolateBoiler2 = ChocolateBoiler.GetInstance();
});
Thread t3 = new Thread(() =>
{
Console.WriteLine("线程3");
chocolateBoiler3 = ChocolateBoiler.GetInstance();
});
t1.Start();
t2.Start();
t3.Start();
Thread.Sleep(2000);
Console.WriteLine(ChocolateBoiler.InstanceCount);
Console.ReadKey();
}
}
public class ChocolateBoiler
{
public bool Empty { get; set; }
public bool Boiled { get; set; }
public static int InstanceCount { get; set; }
private static ChocolateBoiler _uniqueInstance;
private static object _locker = new object();
static ChocolateBoiler()
{
InstanceCount = 0;
}
// 声明为私有构造器
private ChocolateBoiler()
{
Empty = true;
Boiled = false;
}
// 实例访问通道
public static ChocolateBoiler GetInstance()
{
lock (_locker)
{
if (_uniqueInstance == null)
{
InstanceCount++;
_uniqueInstance = new ChocolateBoiler();
}
return _uniqueInstance;
}
}
}
}
解决方法二:提前创建实例
public class ChocolateBoiler
{
public bool Empty { get; set; }
public bool Boiled { get; set; }
public static int InstanceCount { get; set; }
private static ChocolateBoiler _uniqueInstance=new ChocolateBoiler();
static ChocolateBoiler()
{
InstanceCount = 0;
}
// 声明为私有构造器
private ChocolateBoiler()
{
Empty = true;
Boiled = false;
}
// 实例访问通道
public static ChocolateBoiler GetInstance()
{
return _uniqueInstance;
}
}
解决方法三:双重检查枷锁,减小锁定代码的访问,减少同步的次数
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace 单件模式
{
class Program
{
static void Main(string[] args)
{
ChocolateBoiler chocolateBoiler1;
ChocolateBoiler chocolateBoiler2;
ChocolateBoiler chocolateBoiler3;
Thread t1 = new Thread(() =>
{
Console.WriteLine("线程1");
chocolateBoiler1 = ChocolateBoiler.GetInstance();
});
Thread t2 = new Thread(() =>
{
Console.WriteLine("线程2");
chocolateBoiler2 = ChocolateBoiler.GetInstance();
});
Thread t3 = new Thread(() =>
{
Console.WriteLine("线程3");
chocolateBoiler3 = ChocolateBoiler.GetInstance();
});
t1.Start();
t2.Start();
t3.Start();
//var aa = ChocolateBoiler.GetInstance();
//var bb = ChocolateBoiler.GetInstance();
Thread.Sleep(2000);
Console.WriteLine(ChocolateBoiler.InstanceCount);
Console.ReadKey();
}
}
public class ChocolateBoiler
{
public bool Empty { get; set; }
public bool Boiled { get; set; }
public static int InstanceCount { get; set; }
private static ChocolateBoiler _uniqueInstance;
private static object _locker = new object();
static ChocolateBoiler()
{
InstanceCount = 0;
}
// 声明为私有构造器
private ChocolateBoiler()
{
Empty = true;
Boiled = false;
}
// 实例访问通道
public static ChocolateBoiler GetInstance()
{
if (_uniqueInstance == null) // 只有在第一次创建实例时同步
{
lock (_locker)
{
if (_uniqueInstance == null)
{
InstanceCount++;
_uniqueInstance = new ChocolateBoiler();
}
}
}
return _uniqueInstance;
}
}
}