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

闲话策略

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

策略,是为了实现某个目标或者针对某些问题而制定的应对方案,以最终实现目标。比如为实现生娃而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/

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

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

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

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

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

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

时间: 2024-09-16 12:15:15

2.Magicodes.NET框架之路——策略管理的相关文章

1.Magicodes.NET框架之路——起航

1.Magicodes.NET框架之路--起航 前言 从事开发也好几年了,并且最近一直在做架构搭建的工作.这些时间,最大的感悟就是: 只有自己理解了的才是自己的. 对架构这块,若欲立之,必先破之. 故此,才准备利用业余时间来倾力打造这套框架.由于时间精力以及能力有限,也许这套框架初期会有很多不合理之处,但是我相信只要有恒心,这套框架迟早会打磨完美.由于本人秉承做一行爱一行的原则,对代码也比较痴迷,故此命名为"Magicodes框架". Magicodes --意为"Magic

Magicodes.NET框架之路——V0.0.0.5 Beta版发布

最近写代码的时间实在不多,而且今年又打算业余学习下Unity3D以及NodeJs(用于开发游戏后台),因此完善框架的时间更不多了.不过我会一直坚持下去的,同时我也希望有兴趣的同学可以加入Push你的代码. 获取地址:https://github.com/magicodes/Magicodes.NET/releases/tag/V1.0.0.5Beta 文档地址:https://worktile.com/project/4a961c1c28cf4b07bdb4a07f661c7fcf/folder

Magicodes.NET框架之路——让代码再飞一会(ASP.NET Scaffolding)

首先感谢大家对Magicodes.NET框架的支持.就如我上篇所说,框架成熟可能至少还需要一年,毕竟个人力量实在有限.希望有兴趣的小伙伴能够加入我们并且给予贡献.同时有问题的小伙伴请不要在群里询问问题,QQ群仅限于技术交流. 所有有关Magicodes.NET的问题,请在此https://github.com/magicodes/Magicodes.NET/issues页面根据类型提交相应Issues.在使用Magicodes.NET之前,请先查看官方文档并且阅读FAQ(点此阅读). 上篇提到了

Magicodes.NET框架之路——产品之路(谈谈产品管理)

虽然Magicodes.NET现在还不属于产品,但是却不妨碍她想成为产品的心. 为什么突然有了此篇,这篇不是空穴来风,而是我思考良久的结果: 为了让大家知道我在干什么,我想干什么,我将要干什么还有我干了什么 为了让大家清楚Magicodes.NET的产品迭代 为了更好地收集以及管理Bug&需求 为了让我和大家清楚Magicodes.NET的方向 为了更好地团队协作,也为了将来团队的扩张 总之,基于这样或那样的原因,于是有了此篇. 本篇为个人想法与规划,希望和大家多多交流,共同成长. WorkTi

Magicodes.NET框架之路——让Magicodes.NET帮你编写代码

时间总是过得很快,而我几乎没有时间来安安静静的写博客和完善文档.不过总算是框架在一直前进,而我的计划是在今年年底(公历)前,让此框架成熟稳定. 在很长一段时间里,我尝试了很多我之前没有接触的技术或者没用过的技术,比如knockoutJs.OData.T4等等,也许走了很多弯路,也许对框架作用并不大,但是却对我而言却很有价值.只有用过了才知道其可用程度和适用场景,没有使用过就没有发言权. 框架也在不断的重构,我不想照抄别人的路子,我只想做一款有特色的框架,安安静静编码,踏踏实实前进,怎么个特色法呢

如何保持SOA策略管理的正确性

根据基于SOA的服务不同,对SOA策略的定义也多种多样,从商业运作.服务等级管理.控制部署,到安全等等.一般来说,SOA策略管理能够从两个角度来增添价值:它允许基于SOA的服务根据商业变更作出更快? SOA策略管理是一种向面向服务架构战略中注入灵活性和商业价值的高级方式,IT管理者必须要了解SOA策略生命周期中的主要特征,才能帮助你更好地进行控制. 根据基于SOA的服务不同,对SOA策略的定义也多种多样,从商业运作.服务等级管理.控制部署,到安全等等.一般来说,SOA策略管理能够从两个角度来增添

ASP.NET MVC+EF框架+EasyUI实现权限管理系列(3)-面向接口的编程

原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(3)-面向接口的编程 ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇)  (1)框架搭建    (2):数据库访问层的设计Demo 前言:这篇博客在数据访问层的基础上面我们继续学习对这个Demo的开发,希望大家都好好理解一下这个Demo的架构,到最后我实现权限的时候我就简单的说一下搭建过程就OK了,因为这个Demo的思想就是按照权限的设计方式去设计的,下面我们开始介绍面向接口的编程思想,如果感觉好的话可以

使用WiX Toolset创建.NET程序发布Bootstrapper(安装策略管理)(一)——初识WiX

原文:使用WiX Toolset创建.NET程序发布Bootstrapper(安装策略管理)(一)--初识WiX   Visual Studio 打包安装七宗罪           开发.NET的人,肯定会使用Visual Studio里面自带的MSI打包安装工具框架.如果是在一般情况下,这个打包安装框架已经完全足够满足产品发布安装的需要了.它的制成品,是一个setup.exe,一个MSI安装文件,如果你选择项目以来的其他.NET,Windows Install 框架,并且确定随产品发布,那制成

ASP.NET MVC+EF框架+EasyUI实现权限管理系列(24)-权限组的设计和实现(附源码)(终结)

原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(24)-权限组的设计和实现(附源码)(终结) ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇)   (1):框架搭建    (2):数据库访问层的设计Demo    (3):面向接口编程   (4 ):业务逻辑层的封装          (5):前台Jquery easyUI实现   (6):EF上下文实例管理    (7):DBSession的封装   (8):DBSession线程内唯一