2.Magicodes.NET框架之路——策略管理

简介: 闲话策略 策略,有很多解释。但鄙人个人比较看重这点: 策略,是为了实现某个目标或者针对某些问题而制定的应对方案,以最终实现目标。比如为实现生娃而XXOO。 因此在本框架中,策略(Strategy),则是为了实现某些功能或者处理某些特定问题而制定的通用方案或者规则。

闲话策略

策略,有很多解释。但鄙人个人比较看重这点:

策略,是为了实现某个目标或者针对某些问题而制定的应对方案,以最终实现目标。比如为实现生娃而XXOO。

因此在本框架中,策略(Strategy),则是为了实现某些功能或者处理某些特定问题而制定的通用方案或者规则。粗浅一点,你可以理解为XXOO这种方式,不管用啥姿势,归根到底都离不开活塞运动。

如果还不明白,我们举个文明点的例子,比如发送短信,这是系统中常用的功能,也许短信服务商有很多,实现发短信的方式也有很多,但是对于系统来说,只需要的是发送短信这个功能而已,如何让系统的插件都能够使用这个功能,那么我们就需要定制统一的接口来规范,那么根据各个服务商提供的短信发送方式,我们不难理出以下接口:

/// <summary>

/// 短信策略接口

/// </summary>

public interface ISMSStrategy : IStrategyBase

{

/// <summary>

/// 短信服务器地址

/// </summary>

string Url { get; set; }

 

/// <summary>

/// 短信账号

/// </summary>

string UserName { get; set; }

 

/// <summary>

/// 短信密码

/// </summary>

string Password { get; set; }

 

/// <summary>

/// 发送短信

/// </summary>

/// <param name="to">接收人号码</param>

/// <param name="body">短信内容</param>

/// <returns>是否发送成功</returns>

bool Send(string to, string body);

}

不管你是小辣椒还是小冬瓜,还是小XX,通过实现这种策略,组件们都知道怎么发送短信。

Magicodes的基本策略

前面说过,Magicodes框架是一套插件框架,插件要干更多事,要实现一些比较通用的功能,那么就离不开插件策略了。

对于框架来说,将常用的策略纳入框架是很有利于插件调用的。目前,Magicodes框架提供了以下策略:

  • Logger——日志策略
  • Cache——缓存策略
  • Email——邮件策略
  • ScriptMin——脚本资源压缩策略
  • Sesstion——会话策略
  • SMS——短信策略
  • UserAuthentication——用户验证策略

    这些只是一些基本策略,后面还会集成一些通用的支付策略,认证策略等等,当前你也可以自己定制策略。废话先不多说了,我们继续。先说策略管理。

策略管理

对于策略一样,策略管理我们也得合计合计。首先,我们需要一个字典来存储策略。

/// <summary>

/// 策略字典

/// </summary>

static private Lazy<ConcurrentDictionary<string, List<IStrategyBase>>> strategyDictionary = new Lazy<ConcurrentDictionary<string, List<IStrategyBase>>>(() =>

{

return new ConcurrentDictionary<string, List<IStrategyBase>>();

}, LazyThreadSafetyMode.ExecutionAndPublication);

这里有几点需要注意的:

  1. Lazy是用于延迟加载
  2. LazyThreadSafetyMode.ExecutionAndPublication是为了确保线程安全
  3. ConcurrentDictionary是为了确保线程安全,这是.NET 4.0新增的字典集合
  4. 之所以使用List,这是为了考虑有多个同类型策略的存在的情况,比如张三喜欢玩双P,李四喜欢玩3P一样,也许是客户变态,但是也总有特殊的情况。默认,我们将第一项当做默认策略。

为了使用方便,我们再定义一个属性来获取该值:

public ConcurrentDictionary<string, List<IStrategyBase>> StrategyDictionary { get { return strategyDictionary.Value; } }

不然每次都通过strategyDictionary.Value获取,多累啊,而且也不利于框架使用者使用。

接下来,我们需要定义一些公共的方法来方便干活,整个代码定义如下:

/// <summary>

/// 策略管理

/// </summary>

public abstract class StrategyManagerBase

{

/// <summary>

/// 策略字典

/// </summary>

static private Lazy<ConcurrentDictionary<string, List<IStrategyBase>>> strategyDictionary = new Lazy<ConcurrentDictionary<string, List<IStrategyBase>>>(() =>

{

return new ConcurrentDictionary<string, List<IStrategyBase>>();

}, LazyThreadSafetyMode.ExecutionAndPublication);

/// <summary>

/// 策略字典

/// </summary>

public ConcurrentDictionary<string, List<IStrategyBase>> StrategyDictionary { get { return strategyDictionary.Value; } }

/// <summary>

/// 添加策略

/// </summary>

/// <typeparam name="T"></typeparam>

public abstract T AddStrategy<T>(T t) where T : IStrategyBase;

/// <summary>

/// 添加策略

/// </summary>

/// <typeparam name="T"></typeparam>

public abstract T AddStrategy<T>(string key, T t) where T : IStrategyBase;

/// <summary>

/// 添加策略

/// </summary>

/// <typeparam name="T"></typeparam>

public abstract T AddDefaultStrategy<T>(string key, T t) where T : IStrategyBase;

/// <summary>

/// 获取策略

/// </summary>

/// <typeparam name="T"></typeparam>

/// <returns></returns>

public abstract T GetDefaultStrategy<T>() where T : IStrategyBase;

/// <summary>

/// 获取策略

/// </summary>

/// <typeparam name="T">策略类型</typeparam>

/// <param name="key">key</param>

/// <returns></returns>

public abstract T GetDefaultStrategy<T>(string key) where T : IStrategyBase;

/// <summary>

/// 获取策略集合

/// </summary>

/// <typeparam name="T">策略类型</typeparam>

/// <param name="key">key</param>

/// <returns></returns>

public abstract List<T> GetStrategys<T>(string key) where T : IStrategyBase;

/// <summary>

/// 获取策略集合

/// </summary>

/// <typeparam name="T"></typeparam>

/// <returns></returns>

public abstract List<T> GetStrategys<T>() where T : IStrategyBase;

}

从上面可以看出,添加和获取都定义了。而且各位观众,这里可以看到,我将其定义为抽象类了。

这里我忍不住想抛出一个话题,什么时候用虚拟类,什么时候用接口呢?这个我们下回讨论吧,回到正题。

车子看好了,就等彩票了。我们接着实现:

public class StrategyManager : StrategyManagerBase

{

/// <summary>

/// 获取默认策略

/// </summary>

/// <typeparam name="T"></typeparam>

/// <returns></returns>

public override T GetDefaultStrategy<T>()

{

return GetDefaultStrategy<T>(typeof(T).FullName);

}

/// <summary>

/// 添加策略

/// </summary>

/// <typeparam name="T"></typeparam>

/// <param name="t"></param>

public override T AddStrategy<T>(T t)

{

AddStrategy<T>(typeof(T).FullName, t);

return t;

}

/// <summary>

/// 添加策略

/// </summary>

/// <typeparam name="T"></typeparam>

/// <param name="t"></param>

public override T AddStrategy<T>(string key, T t)

{

if (StrategyDictionary.ContainsKey(key))

{

StrategyDictionary[key].Add(t);

}

else

{

var newValue=new List<IStrategyBase>() { t };

StrategyDictionary.AddOrUpdate(key, newValue, (tKey, existingVal) =>

{

return newValue;

});

}

return t;

}

public override T GetDefaultStrategy<T>(string key)

{

if (StrategyDictionary.ContainsKey(key))

return (T)StrategyDictionary[key].First();

return default(T);

}

 

public override List<T> GetStrategys<T>(string key)

{

if (StrategyDictionary.ContainsKey(key))

return StrategyDictionary[key] as List<T>;

return null;

}

 

public override List<T> GetStrategys<T>()

{

return GetStrategys<T>(typeof(T).FullName);

}

 

public override T AddDefaultStrategy<T>(string key, T t)

{

if (StrategyDictionary.ContainsKey(key))

{

StrategyDictionary[key].Add(t);

//反转元素,使后来居上

StrategyDictionary[key].Reverse();

}

else

{

var newValue = new List<IStrategyBase>() { t };

StrategyDictionary.AddOrUpdate(key, newValue, (tKey, existingVal) =>

{

return newValue;

});

}

return t;

}

}

你看一无所有,搞了个儿子出来了,也就是间接证明了,彩票换车子是可以的。所以古人云"书中自有黄金屋,书中自有颜如玉",古人诚不欺我!!

这里就没太多讲解点了,只是语法的使用了。值得讨论的,就是设计理念了。对于架构,设计理念才是最重要的。之所以这么设计,我是为了追求灵活,比如需要获取日志策略:

public override ILoggerStrategy ApplicationLog

{

get

{

return this.StrategyManager.GetDefaultStrategy<ILoggerStrategy>();

}

}

这样获取的话,避免了传统的设计方式,比如(下面代码Word中手写,乱的话也请忍受下,Word发博确实不方便,每次发了都得调,心里大骂微软三声):

Public class A

{

Public ILoggerStrategy LoggerStrategy{get;set;}


}

如果是这么设计的话,每添加一个策略,老子都得改这个类,这是增加我的负担。另外也方便插件定义自己的策略,假如某XX1(插件)定义了一个微信推送的策略,那么XX2(插件)只需引用这个插件就好,策略还是共享的,不增加大家的工作量,也不增加我的工作量,大家都好。

 

最后

之前此贴用【MagicCode起航】账号发布过,这里重新发布过。以后Magicodes框架的博客都会使用此账号发布。

Magicodes框架现在已经免费开源下载了,具体请访问http://www.magicodes.net/

策略核心部分介绍完了,觉得设计方面有问题,请尽管提,大家都是相互学习提升。

在程序员的世界里,技术不仅仅是技术。

在架构师的眼里,技术也不再是技术。

接下来,我将介绍日志策略以及其实现。

--------------------------------------------------分割线------------------------------------------------------------------

本框架将会长期维护并且更新下去,而且尽量每周分享一篇技术贴或者架构心得贴,以促进大家共同进步,如有不对的地方,请各位大神指正。

目录
相关文章
|
9天前
|
设计模式 开发框架 JavaScript
基于.NET8 + Vue/UniApp前后端分离的快速开发框架,开箱即用!
基于.NET8 + Vue/UniApp前后端分离的快速开发框架,开箱即用!
|
1月前
|
XML JSON API
ServiceStack:不仅仅是一个高性能Web API和微服务框架,更是一站式解决方案——深入解析其多协议支持及简便开发流程,带您体验前所未有的.NET开发效率革命
【10月更文挑战第9天】ServiceStack 是一个高性能的 Web API 和微服务框架,支持 JSON、XML、CSV 等多种数据格式。它简化了 .NET 应用的开发流程,提供了直观的 RESTful 服务构建方式。ServiceStack 支持高并发请求和复杂业务逻辑,安装简单,通过 NuGet 包管理器即可快速集成。示例代码展示了如何创建一个返回当前日期的简单服务,包括定义请求和响应 DTO、实现服务逻辑、配置路由和宿主。ServiceStack 还支持 WebSocket、SignalR 等实时通信协议,具备自动验证、自动过滤器等丰富功能,适合快速搭建高性能、可扩展的服务端应用。
109 3
|
9天前
|
消息中间件 监控 数据可视化
基于.NET开源、功能强大且灵活的工作流引擎框架
基于.NET开源、功能强大且灵活的工作流引擎框架
|
9天前
|
开发框架 网络协议 .NET
C#/.NET/.NET Core优秀项目和框架2024年10月简报
C#/.NET/.NET Core优秀项目和框架2024年10月简报
|
9天前
|
网络协议 Unix Linux
精选2款C#/.NET开源且功能强大的网络通信框架
精选2款C#/.NET开源且功能强大的网络通信框架
|
9天前
|
开发框架 JavaScript 前端开发
2024年全面且功能强大的.NET快速开发框架推荐,效率提升利器!
2024年全面且功能强大的.NET快速开发框架推荐,效率提升利器!
|
9天前
|
网络协议 网络安全 Apache
一个整合性、功能丰富的.NET网络通信框架
一个整合性、功能丰富的.NET网络通信框架
|
1月前
|
设计模式 前端开发 C#
使用 Prism 框架实现导航.NET 6.0 + WPF
使用 Prism 框架实现导航.NET 6.0 + WPF
87 10
|
1月前
|
开发框架 前端开发 API
C#/.NET/.NET Core优秀项目和框架2024年9月简报
C#/.NET/.NET Core优秀项目和框架2024年9月简报
|
1月前
|
Linux C# Android开发
.NET开源跨平台桌面和移动应用的统一框架 - Eto.Forms
.NET开源跨平台桌面和移动应用的统一框架 - Eto.Forms
137 1

热门文章

最新文章

下一篇
无影云桌面