设计模式 一般初级、中级、高级程序员都喜欢挂在嘴边的词。想必大家身边也有不少关于设计模式的书。设计模式是程序员的老前辈们根据自己的项目经验积累起来的解决方案集。所以,没必要把设计模式看成是硬性的东西,别人的经验参考一下即可,了解设计思路,为什么这种场景要用这种模式。也许是老一辈的程序员们确实比现在的程序员要强很多,毕竟现在网上很难找到自己摸索的设计模式了。
虫子不才就先抛砖引玉了。
简单介绍2个我项目中经常用到的模式
1.机器人插件模式
何所谓机器人插件,可以这样理解。你有一个机器人,但是需要这个机器人干什么并不确定。插入不同的卡片可以让机器人做出不同的行为。原理和aop类似,aop是站在系统级的角度,插件模式基于行为。
直接看代码
定义行为:
View Code public static event EventHandler<RobotCancelEventArgs> DeleteingRobot;
protected virtual void OnDeleteingRobot(RobotCancelEventArgs e)
{
EventHandler<RobotCancelEventArgs> tmp = DeleteingRobot;
if (tmp !=
null)
tmp(
this, e);
}
public static event EventHandler<RobotCancelEventArgs> bhingRobot;
/// <summary> /// 机器人行动前触发事件 /// </summary> protected virtual void OnbhingRobot(RobotCancelEventArgs e)
{
EventHandler<RobotCancelEventArgs> tmp = bhingRobot;
if (tmp !=
null)
tmp(
this, e);
}
public static event EventHandler<EventArgs> bhedRobot;
/// <summary> /// 机器人行动后触发 /// </summary> protected virtual void OnbhedRobot(EventArgs e)
{
EventHandler<EventArgs> tmp = bhedRobot;
if (tmp !=
null)
tmp(
this, e);
}
public static event EventHandler<ServingEventArgs> ServingRobot;
/// <summary> /// 调用机器人行为时触发 /// </summary> protected virtual void OnServing(ServingEventArgs e)
{
EventHandler<ServingEventArgs> tmp = ServingRobot;
if (tmp !=
null)
tmp(
this, e);
}
行为实例:
View Code public bool bhRobot(
out string Message)
{
Message =
string.Empty;
RobotCancelEventArgs e =
new RobotCancelEventArgs();
OnServing(e);
if (!e.Cancel)
{
var v = RobotService.bhRobot(
this,
out Message);
if (v)
{
OnbhedRobot(EventArgs.Empty);
return true;
}
return false;
}
else {
Message = e.Message;
return false;
}
}
注册卡片:
View Code [Extension(
"",
" 1.0 ",
" 熬夜的虫子 ")]
public class CardRobot
{
static CardRobot()
{
Robot.ServingRobot +=
new EventHandler<ServingEventArgs>(Comment_ServingDelegate);
}
static void Comment_ServingDelegate(
object sender, ServingEventArgs e)
{
try {
// do something }
catch (Exception ex)
{
// Log4N.WarnLog("BadWordFilterExtension Exception:", ex); }
}
}
根据自定义属性反射加载
View Code void Application_Start(
object sender, EventArgs e)
{
ExtensionManager.InitExtension();
System.IO.DirectoryInfo di =
new System.IO.DirectoryInfo(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
" bin "));
foreach (var item
in di.GetFiles(
" *.dll ", System.IO.SearchOption.TopDirectoryOnly))
{
System.Reflection.Assembly assembly = System.Reflection.Assembly.LoadFrom(item.FullName);
Type[] types = assembly.GetTypes();
foreach (Type type
in types)
{
object[] attributes = type.GetCustomAttributes(
typeof(CommentEngine.Core.ExtensionAttribute),
false);
foreach (
object attribute
in attributes)
{
if (ExtensionManager.ExtensionIsEnable(type.Name))
assembly.CreateInstance(type.FullName);
}
}
}
}
2.单例扩展模式
先看看传统的单例模式 撇开懒汉式等区分
负责创建Singleton类自己的唯一实例,并提供一个getInstance的方法,让外部来访问这个类的唯一实例。
View Code public static T GetInstance(
object lockKey, T instance, Func<T> onCreateInstance)
{
if (instance ==
null)
{
if (lockKey ==
null)
lockKey = LockKey;
lock (lockKey)
{
if (instance ==
null)
{
try {
if (onCreateInstance ==
null)
instance =
new T();
else instance = onCreateInstance();
}
catch {
instance =
default(T);
}
}
}
}
return instance;
}
优点:节省系统资源。
适用场景:
当需要控制一个类的实例只能有一个,而且客户只能从一个全局访问点访问它时,可以选用单例模式,这些功能恰好是单例模式要解决的问题。
扩展场景:
海量即时消息,消息处理机制含有复杂逻辑,体积庞大。这个时候你用单例模式可能导致消息不即时,不用单例资源占用太大。
可能有人就会思考,能不能控制实例数目为2个,3个,或者是任意多个呢?目的都是一样的,节约资源啊,有些时候单个实例不能满足实际的需要,会忙不过来,根据测算,6个实例刚刚好。
思路很简单,就是利用上面通过Map来缓存实现单例的示例,进行变形,一个Map可以缓存任意多个实例。
也可以做得更通用一点,将单例的似有构造函数公开。实例的排他性通过对象锁来实现
部分代码
View Code private static Hashtable<String, Example> map =
new System.Collections.Hashtable();
private static int flag =
1;
private static int MAX =
6;
public static Example getInstance()
{
String value =
" aoyedechongzi " + flag;
Example Example = map.
get(value);
if (Example ==
null)
{
Example =
new Example();
map.put(value, Example);
}
flag++;
if (flag > MAX)
{
flag =
1;
}
return Example;
}
本文转自 熬夜的虫子 51CTO博客,原文链接:http://blog.51cto.com/dubing/712401