大连餐饮网站建设,网站标题写什么作用是什么意思,扶沟县网站开发,没有网站怎么快速做cps大家好#xff0c;以后我会用23篇文章#xff0c;来给大家讲解设计模式#xff0c;当然如果你看过我的项目#xff0c;很多设计模式已经很会了#xff0c;只是没有注意到#xff0c;我这里会讲解一下#xff0c;大家就会发现#xff0c;如果你看懂了我的项目#xff0… 大家好以后我会用23篇文章来给大家讲解设计模式当然如果你看过我的项目很多设计模式已经很会了只是没有注意到我这里会讲解一下大家就会发现如果你看懂了我的项目其实已经至少学会了六种设计模式了。 一、什么是单例模式【单例模式】英文名称Singleton Pattern这个模式很简单一个类型只需要一个实例他是属于创建类型的一种常用的软件设计模式。通过单例模式的方法创建的类在当前进程中只有一个实例根据需要也有可能一个线程中属于单例如仅线程上下文内使用同一个实例。1、单例类只能有一个实例。2、单例类必须自己创建自己的唯一实例。3、单例类必须给所有其他对象提供这一实例。那咱们大概知道了其实说白了就是我们整个项目周期内只会有一个实例当项目停止的时候实例销毁当重新启动的时候我们的实例又会产品。上文中说到了一个名词【创建类型】的设计模式那什么是创建类型的设计模式呢创建型Creational模式负责对象创建我们使用这个模式就是为了创建我们需要的对象实例的。那除了创建型还有其他两种类型的模式 -结构型Structural模式处理类与对象间的组合 -行为型Behavioral模式类与对象交互中的职责分这两种设计模式以后会慢慢说到这里先按下不表。咱们就重点从0开始分析分析如何创建一个单例模式的对象实例。 二、如何创建单例模式实现单例模式有很多方法从“懒汉式”到“饿汉式”最后“双检锁”模式。这里咱们就慢慢的从一步一步的开始讲解如何创建单例既然要创建单一的实例那我们首先需要学会如何去创建一个实例这个很简单相信每个人都会创建实例就比如说这样的 /// summary /// 定义一个天气类 /// /summary public class WeatherForecast { public DateTime Date { get; set; } DateTime.Now; public int TemperatureC { get; set; } public int TemperatureF 32 (int)(TemperatureC / 0.5556); public string Summary { get; set; } } [HttpGet]
public WeatherForecast Get()
{ // 实例化一个对象实例 WeatherForecast weather new WeatherForecast(); return weather;
} 我们每次访问的时候时间都是会变化所以我们的实例也是一直在创建在变化相信每个人都能看到这个代码是什么意思不多说直接往下走我们知道单例模式的核心目的就是必须保证这个实例在整个系统的运行周期内是唯一的这样可以保证中间不会出现问题。那好我们改进改进不是说要唯一一个么好说我直接返回不就行了 /// summary /// 定义一个天气类 /// /summary public class WeatherForecast { // 定义一个静态变量来保存类的唯一实例 private static WeatherForecast uniqueInstance; // 定义私有构造函数使外界不能创建该类实例 private WeatherForecast() { } /// summary /// 静态方法来返回唯一实例 /// 如果存在则返回 /// /summary /// returns/returns public static WeatherForecast GetInstance() { // 如果类的实例不存在则创建否则直接返回 // 其实严格意义上来说这个不属于【单例】 if (uniqueInstance null) { uniqueInstance new WeatherForecast(); } return uniqueInstance; } public DateTime Date { get; set; } DateTime.Now; public int TemperatureC { get; set; } public int TemperatureF 32 (int)(TemperatureC / 0.5556); public string Summary { get; set; } } 然后我们修改一下调用方法因为我们的默认构造函数已经私有化了不允许再创建实例了所以我们直接这么调用[HttpGet] public WeatherForecast Get() { // 实例化一个对象实例 WeatherForecast weather WeatherForecast.GetInstance(); return weather; } 最后来看看效果这个时候我们可以看到时间已经不发生变化了也就是说我们的实例是唯一的了大功告成是不是很开心但是别着急问题来了我们目前是单线程的所以只有一个那如果多线程呢如果多个线程同时访问会不会也会正常呢这里我们做一个测试我们在项目启动的时候用多线程去调用 public WeatherForecast Get() { // 实例化一个对象实例 //WeatherForecast weather WeatherForecast.GetInstance(); // 多线程去调用 for (int i 0; i 3; i) { var th new Thread( new ParameterizedThreadStart((state) { WriteWeather(); }) ); th.Start(i); } return null; }然后我们看看效果是怎样的按照我们的思路应该是只会走一遍构造函数其实不是3个线程在第一次访问GetInstance方法时同时判断(uniqueInstance null)这个条件时都返回真然后都去创建了实例这个肯定是不对的。那怎么办呢只要让GetInstance方法只运行一个线程运行就好了我们可以加一个锁来控制他代码如下public class WeatherForecast { // 定义一个静态变量来保存类的唯一实例 private static WeatherForecast uniqueInstance; // 定义一个锁防止多线程 private static readonly object locker new object(); // 定义私有构造函数使外界不能创建该类实例 private WeatherForecast() { } /// summary /// 静态方法来返回唯一实例 /// 如果存在则返回 /// /summary /// returns/returns public static WeatherForecast GetInstance() { // 当第一个线程执行的时候会对locker对象 加锁 // 当其他线程执行的时候会等待 locker 执行完解锁 lock (locker) { // 如果类的实例不存在则创建否则直接返回 if (uniqueInstance null) { uniqueInstance new WeatherForecast(); } } return uniqueInstance; } public DateTime Date { get; set; } DateTime.Now; public int TemperatureC { get; set; } public int TemperatureF 32 (int)(TemperatureC / 0.5556); public string Summary { get; set; } }这个时候我们再并发测试发现已经都一样了这样就达到了我们想要的效果但是这样真的是最完美的么其实不是的因为我们加锁只是第一次判断是否为空如果创建好了以后以后就不用去管这个 lock 锁了我们只关心的是 uniqueInstance 是否为空那我们再完善一下 /// summary /// 定义一个天气类 /// /summary public class WeatherForecast { // 定义一个静态变量来保存类的唯一实例 private static WeatherForecast uniqueInstance; // 定义一个锁防止多线程 private static readonly object locker new object(); // 定义私有构造函数使外界不能创建该类实例 private WeatherForecast() { } /// summary /// 静态方法来返回唯一实例 /// 如果存在则返回 /// /summary /// returns/returns public static WeatherForecast GetInstance() { // 当第一个线程执行的时候会对locker对象 加锁 // 当其他线程执行的时候会等待 locker 执行完解锁 if (uniqueInstance null) { lock (locker) { // 如果类的实例不存在则创建否则直接返回 if (uniqueInstance null) { uniqueInstance new WeatherForecast(); } } } return uniqueInstance; } public DateTime Date { get; set; } DateTime.Now; public int TemperatureC { get; set; } public int TemperatureF 32 (int)(TemperatureC / 0.5556); public string Summary { get; set; } }这样才最终的完美实现我们的单例模式搞定。 三、我们在哪里遇到过如果你看过我的 Blog.Core 项目的话肯定看到过 Redis 那部分我在那里就是封装了一个单例感兴趣的可以看看public class RedisCacheManager : IRedisCacheManager { private readonly string redisConnenctionString; public volatile ConnectionMultiplexer redisConnection; private readonly object redisConnectionLock new object(); public RedisCacheManager() { string redisConfiguration Appsettings.app(new string[] { AppSettings, RedisCachingAOP, ConnectionString });//获取连接字符串 if (string.IsNullOrWhiteSpace(redisConfiguration)) { throw new ArgumentException(redis config is empty, nameof(redisConfiguration)); } this.redisConnenctionString redisConfiguration; this.redisConnection GetRedisConnection(); } /// summary /// 核心代码获取连接实例 /// 通过双if 夹lock的方式实现单例模式 /// /summary /// returns/returns private ConnectionMultiplexer GetRedisConnection() { //如果已经连接实例直接返回 if (this.redisConnection ! null this.redisConnection.IsConnected) { return this.redisConnection; } //加锁防止异步编程中出现单例无效的问题 lock (redisConnectionLock) { if (this.redisConnection ! null) { //释放redis连接 this.redisConnection.Dispose(); } try { this.redisConnection ConnectionMultiplexer.Connect(redisConnenctionString); } catch (Exception) { //throw new Exception(Redis服务未启用请开启该服务并且请注意端口号本项目使用的的6319而且我的是没有设置密码。); } } return this.redisConnection; } /// summary /// 清除 /// /summary public void Clear() { foreach (var endPoint in this.GetRedisConnection().GetEndPoints()) { var server this.GetRedisConnection().GetServer(endPoint); foreach (var key in server.Keys()) { redisConnection.GetDatabase().KeyDelete(key); } } } /// summary /// 判断是否存在 /// /summary /// param namekey/param /// returns/returns public bool Get(string key) { return redisConnection.GetDatabase().KeyExists(key); } /// summary /// 查询 /// /summary /// param namekey/param /// returns/returns public string GetValue(string key) { return redisConnection.GetDatabase().StringGet(key); } /// summary /// 获取 /// /summary /// typeparam nameTEntity/typeparam /// param namekey/param /// returns/returns public TEntity GetTEntity(string key) { var value redisConnection.GetDatabase().StringGet(key); if (value.HasValue) { //需要用的反序列化将Redis存储的Byte[]进行反序列化 return SerializeHelper.DeserializeTEntity(value); } else { return default(TEntity); } } /// summary /// 移除 /// /summary /// param namekey/param public void Remove(string key) { redisConnection.GetDatabase().KeyDelete(key); } /// summary /// 设置 /// /summary /// param namekey/param /// param namevalue/param /// param namecacheTime/param public void Set(string key, object value, TimeSpan cacheTime) { if (value ! null) { //序列化将object值生成RedisValue redisConnection.GetDatabase().StringSet(key, SerializeHelper.Serialize(value), cacheTime); } } /// summary /// 增加/修改 /// /summary /// param namekey/param /// param namevalue/param /// returns/returns public bool SetValue(string key, byte[] value) { return redisConnection.GetDatabase().StringSet(key, value, TimeSpan.FromSeconds(120)); } }好啦今天的设计模式你学会了么在我的项目中还隐藏了工厂模式装饰器模式中介者模式观察者模式享元模式等等等等下次再见咯。