C#设计模式整理
我居然连一月一随笔都没有,啊啊啊,忙死个人
这个随笔主要是记录基于自己学习[美]James W.Cooper著的《C# Design Patterns : A Tutorial》一书中常用设计模式的整理,既是自己整理的,便避免不了理解偏差,欢迎分享宝贵见解。
Behavioral Pattern 行为型模式
行为型模式模式主要与对象间的通信有关。
Chain of Responsibility(职责链模式),职责链模式减少对象间的耦合。整理了一个接口,如下:
- /// <summary>
- /// 职责链模式
- /// 职责链减少了类之间的耦合
- /// </summary>
- /// <typeparam name="T"></typeparam>
- public interface IChain<T>
- {
- /// <summary>
- /// 添加一条链至本链后
- /// </summary>
- /// <param name="nextChain"></param>
- void AddNext(IChain<T> nextChain);
- /// <summary>
- /// 消息处理
- /// </summary>
- /// <param name="msg"></param>
- void OnChain(T msg);
- }
适用:
p) 职责链模式允许多个类处理同一个请求,请求在类之间传递,直到其中一个类处理它为止。
p) 不想把相互作用的内容放在调用程序里。
举例:
例2:
最近想关于硬件命令和数据收发时想到了用职责链解决,结果好像出现了偏差,便有了以下代码。以下代码用于统计字符串中JMB三个字母出现的次数以及J出现的次数以及两个B字母间用时(实属瞎JB写)。
以下是相关类定义:
- using System;
- using System.Collections.Generic;
- namespace ConcurrencySolution
- {
- #region base classes
- public class Msg
- {
- public string ID
- {
- get { return _id; }
- }
- private string _id;
- public Msg()
- {
- _id = Guid.NewGuid().ToString("N");
- }
- }
- public class MsgRep
- {
- public string MsgID;
- public bool ExecResult;
- public MsgRep()
- : this(string.Empty, false)
- { }
- public MsgRep(string vMsgID, bool vExecResult)
- {
- MsgID = vMsgID;
- ExecResult = vExecResult;
- }
- }
- public abstract class Chain
- {
- public Chain Next
- {
- get { return _next; }
- }
- private Chain _next;
- public void SetNext(Chain next)
- {
- _next = next;
- }
- public MsgRep HandleMsg(Msg msg)
- {
- MsgRep rep = HandleMessage(msg);
- if (true == rep.ExecResult)
- return rep;
- if (Next != null)
- return Next.HandleMsg(msg);
- return null;
- }
- protected abstract MsgRep HandleMessage(Msg msg);
- }
- public abstract class Worker : Chain
- {
- public string WorkerID
- {
- get { return _workerID; }
- }
- protected string _workerID;
- protected Worker()
- : this(string.Empty)
- { }
- protected Worker(string vWorkerID)
- {
- _workerID = vWorkerID;
- }
- protected override MsgRep HandleMessage(Msg msg)
- {
- WorkerMsg wmsg = msg as WorkerMsg;
- if (null == wmsg)
- throw new ArgumentException("isn't a valid WorkerMsg", "msg");
- var rep = DoWork(wmsg);
- return rep;
- }
- protected abstract WorkerMsgRep DoWork(WorkerMsg msg);
- }
- #endregion
- public class WorkerMsg : Msg
- {
- public string Action
- {
- get { return _action; }
- }
- private string _action;
- public WorkerMsg(string vAction)
- : base()
- {
- _action = vAction;
- }
- }
- public class WorkerMsgRep : MsgRep
- {
- public string WorkerID;
- public WorkerMsgRep()
- : this(string.Empty, false, string.Empty)
- { }
- public WorkerMsgRep(string vMsgID, bool vExecResult, string vWorkerID)
- : base(vMsgID, vExecResult)
- {
- WorkerID = vWorkerID;
- }
- }
- #region Workers
- public class WorkerJ : Worker
- {
- public int MentionTimes
- {
- get { return _mentionTimes; }
- }
- protected int _mentionTimes;
- protected WorkerJ()
- : base()
- { }
- public WorkerJ(string vWorkerID)
- : base(vWorkerID)
- { }
- protected override WorkerMsgRep DoWork(WorkerMsg msg)
- {
- WorkerMsgRep rep = new WorkerMsgRep(msg.ID, false, WorkerID);
- rep.ExecResult = msg.Action == "J";
- if (true == rep.ExecResult)
- _mentionTimes++;
- return rep;
- }
- public virtual void ChangeWorkerID(string vWorkerID)
- {
- throw new NotImplementedException();
- }
- }
- public class WorkerM : Worker
- {
- public WorkerM(string vWorkerID)
- : base(vWorkerID)
- { }
- protected override WorkerMsgRep DoWork(WorkerMsg msg)
- {
- var rep = new WorkerMsgRep(msg.ID, false, WorkerID);
- if (msg.Action == "M")
- rep.ExecResult = true;
- return rep;
- }
- }
- public class WorkerB : Worker
- {
- public List<DateTime> MentionTime
- {
- get { return _mentionTime; }
- }
- List<DateTime> _mentionTime;
- public WorkerB(string vWorkerID)
- : base(vWorkerID)
- {
- _mentionTime = new List<DateTime>();
- }
- protected override WorkerMsgRep DoWork(WorkerMsg msg)
- {
- WorkerMsgRep rep = new WorkerMsgRep(msg.ID, false, WorkerID);
- rep.ExecResult = msg.Action == "B";
- if (true == rep.ExecResult)
- _mentionTime.Add(DateTime.Now);
- return rep;
- }
- }
- #endregion
- }
以下是使用:
- public void TestMethod1()
- {
- string testStr = "Bb1123lkiJMoBp";
- WorkerJ wj = new WorkerJ("j");
- WorkerM wm = new WorkerM("m");
- WorkerB wb = new WorkerB("B");
- wj.SetNext(wm);
- wm.SetNext(wb);
- int countJMB = ;
- WorkerMsg ms;
- WorkerMsgRep mr;
- for (int i = ; i < testStr.Length; i++)
- {
- ms = new WorkerMsg(testStr[i].ToString());
- mr = wj.HandleMsg(ms) as WorkerMsgRep;
- if (mr != null &&
- true == mr.ExecResult)
- countJMB++;
- }
- string time1 = wb.MentionTime[].ToString("HH:mm:ss:ms");
- string time2 = wb.MentionTime[].ToString("HH:mm:ss:ms");
- ;
- }
例1:
- public class Sunday : IChain<DayOfWeek> // System.DayOfWeek
- {
- private IChain<DayOfWeek> _next;
- private DayOfWeek _token;
- public DayOfWeek Token { get { return _token; } }
- public Sunday()
- {
- _token = DayOfWeek.Sunday;
- }
- #region IChain<DayOfWeek> 成员
- void IChain<DayOfWeek>.AddNext(IChain<DayOfWeek> nextChain)
- {
- _next = nextChain;
- }
- void IChain<DayOfWeek>.OnChain(DayOfWeek msg)
- {
- if (DayOfWeek.Sunday == msg) // 此处判断本类是否最适合处理此消息
- {
- Console.WriteLine("Hello! It's {0}, u'd better study!", _token);
- }
- else if (_next != null) // 传递消息
- {
- _next.OnChain(msg);
- }
- else
- {
- throw new Exception(string.Format("{0} can't handle this msg : {1}", _token, msg));
- }
- }
- #endregion
- }
- public class DefaultDay : IChain<DayOfWeek>
- {
- private DayOfWeek _token;
- public DayOfWeek Token { get { return _token; } }
- public DefaultDay()
- {
- //_token = DayOfWeek.None; 好烦啊,想偷个懒的,意思到就好了8
- }
- #region IChain<DayOfWeek> 成员
- void IChain<DayOfWeek>.AddNext(IChain<DayOfWeek> nextChain)
- {
- throw new NotImplementedException(string.Format("Sorry but i'm at the end of the chain, {0} said.", _token));
- }
- void IChain<DayOfWeek>.OnChain(DayOfWeek msg)
- {
- //if (msg != _token)
- //{
- // throw new Exception(string.Format("It's none of my business about : {0}, {1} said", msg, _token));
- //}
- //else
- //{
- Console.WriteLine("Unbelievable! Today is {0}!", _token);
- //}
- }
- #endregion
- }
- public class ChainImpl
- {
- IChain<DayOfWeek> _prior, _inferior, _default;
- public ChainImpl()
- {
- _prior = new Sunday();
- //_inferior = new Monday();
- _default = new DefaultDay();
- //_prior.AddNext(_inferior);
- //_inferior.AddNext(_default);
- _prior.AddNext(_default);
- }
- public void Work(DayOfWeek today)
- {
- // 不管今天具体是周几,由_prior对象优先去处理
- // 如果_prior对象不能处理,自动转交给它的"下一链"处理直到_default
- _prior.OnChain(today);
- }
- }
Strategy Pattern(策略模式)。
适用:
p) 不同算法各自封装,可随意挑选需要的算法。
实现:
方式一,把策略封装在单独的类中。策略决策类和策略类间的耦合较低(当更换策略时,策略决策类与原策略类解耦);可提供异步获取结果的方法;
方式二,把策略作为一个委托(根据自己理解实现的,自荐)。性能(反射)可能较低;策略决策类与策略(委托,当为其他类中的方法时)所属类间的耦合较高;策略相对轻量级、灵活方便;对于同个问题的策略,可封装在单独类中,结构清晰;
举例:
方式二,具体实现。
- using System;
- public class StrategyDecision
- {
- protected Delegate _strategy;
- public StrategyDecision()
- { }
- public StrategyDecision(Delegate strategy)
- {
- _strategy = strategy;
- }
- ~StrategyDecision()
- {
- _strategy = null;
- }
- public object GetResult(params object[] args)
- {
- try
- {
- return _strategy.DynamicInvoke(args);
- }
- catch (Exception e)
- {
- throw e;
- }
- }
- public void ChangeStrategy(Delegate strategy)
- {
- _strategy = strategy;
- }
- }
方式二,使用举例。
- var obj = new StrategyDecision(
- new Func<int, int, int>(
- (oa, ob) =>
- {
- return oa + ob;
- })).GetResult(7, 7); // Bad example! 图简便 >_<
Creational Pattern 创建型模式
所有创建型模式都涉及到创建对象实例的方式。将创建对象过程抽象成一个专门的“创建器”类,会使程序更灵活、更通用。
Singleton Pattern(单例模式),单例模式限制而不是改进类的创建,单例模式保证一个类有且只有一个实例,并提供一个访问它的全局访问点。如果有需要,也可以在类中保存少数几个实例。我常用单例的全局访问功能;在你只持有一个资源,而需要对外开放多个资源访问服务时,用单例是很好的选择。
举例:
- public class Myself
- {
- static readonly Myself _instance;
- public static Myself Instance
- {
- get { return _instance; }
- }
- // 应用程序域中第一次发生以下事件时将触发静态构造函数的执行:
- //• 创建类类型的实例。(外部无法创建本类实例)
- //• 引用类类型的任何静态成员。(当Instance属性被引用时)
- static Myself()
- {
- _instance = new Myself();
- }
- private Myself() // 私有构造限制外部创建实例
- { }
- }
备注:
此单例的实现是我根据静态构造的特性实现的,以下称前者;书中的单例用lock方式实现,以下称后者。我用循环1000次调用某单例的两种实现的方法(简单返回字符串):第一次调用前者用时0毫秒,后者用时2毫秒,也就是说后者用时是在第一次调用(也就是构造函数花费的)时出现的,以后每次调用二者都是0毫秒;值得一提的点,每个1000次调用中,后者总会至少有一次返回空,也就是调用失败或者啥,但前者不会有这种情况,也就是说前者较为安全。有时间我把测试也贴出来。
Linkin Park 的《Halfway Right》好听哭了T_T,一定要听!
C#设计模式整理的更多相关文章
- JAVA常用设计模式整理
设计模式:一个程序员对设计模式的理解:“不懂”为什么要把很简单的东西搞得那么复杂.后来随着软件开发经验的增加才开始明白我所看到的“复杂”恰恰就是设计模式的精髓所在,我所理解的“简单”就是一把钥匙开一把 ...
- JavaScript 中常见设计模式整理
开发中,我们或多或少地接触了设计模式,但是很多时候不知道自己使用了哪种设计模式或者说该使用何种设计模式.本文意在梳理常见设计模式的特点,从而对它们有比较清晰的认知. JavaScript 中常见设计模 ...
- python设计模式整理
设计模式的定义:为了解决面向对象系统中重要和重复的设计封装在一起的一种代码实现框架,可以使得代码更加易于扩展和调用 四个基本要素:模式名称,问题,解决方案,效果 六大原则: 1.开闭原则:一个软件实体 ...
- js设计模式整理
单例模式 恶汉式单例 实例化时 懒汉式单例 调用时构造函数模式 1.实现一 function Car(model, year, miles) { this.model = model; this.ye ...
- Java设计模式整理
一.创建型模式 1.抽象工厂模式(AbstractFactory): 提供一个接口, 用于创建相关或依赖对象的家族, 而不需要指定具体类. 案例:https://www.cnblogs.com/lfx ...
- php设计模式 1单例模式
之前很长时间之前就学习过设计模式,但是因为在实践中很少应用,所以忽略了,但现在却意识到设计模式很重要的,程序设计简介高效冗余性代码少. 今天开始把前几天学习的几个设计模式整理一下,首先当然是单例模式. ...
- Java开发中的23种设计模式(转)
设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...
- 《JavaScript 模式》知识点小抄本(下)
介绍 最近开始给自己每周订个学习任务,学习结果反馈为一篇文章的输出,做好学习记录. 这一周(02.25-03.03)我定的目标是<JavaScript 模式>的第七章学习一遍,学习结果的反 ...
- 手写MyBatis流程
MyBatis 手写MyBatis流程 架构流程图 封装数据 封装到Configuration中 1.封装全局配置文件,包含数据库连接信息和mappers信息 2.封装*mapper.xml映射文件 ...
随机推荐
- .NET Core使用微软官方类库实现汉字转拼音
一.NuGet包 拼音:Install-Package SimplifiedChinesePinYinConversion 简体-繁体互转:Install-Package TraditionalChi ...
- maven工程,java代码加载resources下面资源文件的路径
1 通过类加载器加载器, 1. URL resource = TestMain.class.getResource("/18500228040.txt");File file = ...
- python selenium鼠标键盘操作(ActionChains)
用selenium做自动化,有时候会遇到需要模拟鼠标操作才能进行的情况,比如单击.双击.点击鼠标右键.拖拽等等.而selenium给我们提供了一个类来处理这类事件--ActionChains sele ...
- SpringBoot编写自定义的starter 专题
What’s in a name All official starters follow a similar naming pattern; spring-boot-starter-*, where ...
- nodejs版本更新问题:express不是内部或外部命令
版本更新后,我们使用熟悉的npm install -g express命令安装,但是,安装成功之后居然提示express不是内部或外部命令. nodejs小问题:[1]express不是内部或外部命令 ...
- linux 显示当前所在文件位置 以及git 分支所在
function git-branch-name { git symbolic-ref HEAD 2>/dev/null | cut -d"/" -f 3}function ...
- 面试时怎样回答:你对原生ajax的理解
很多人跟我一样用习惯了jq封装好的$.ajax,但是面试时,原生ajax是很多面试官喜欢问的问题,今天再查资料,打算好好整理一下自己理解的原生ajax. 首先,jq的ajax:一般我常用的参数就是这些 ...
- CFile类的open方法中的参数说明
CFile::Open是在MFC里面,打开一个文件的方法. Open函数的原型如下: virtual BOOL Open( LPCTSTR lpszFileName, UINT nOpenFlags, ...
- redis结合自定义注解实现基于方法的注解缓存,及托底缓存的实现
本次分享如何使用redis结合自定义注解实现基于方法的注解缓存,及托底缓存的实现思路 现在的互联网公司大多数都是以Redis作为缓存,使用缓存的优点就不赘述了,写这篇文章的目的就是想帮助同学们如 ...
- BZOJ4554: [Tjoi2016&Heoi2016]游戏 luoguP2825 loj2057
题面描述:尽可能多的放置符合要求的炸弹. 分析: 在i,j处放置炸弹,则在第i行,上一个硬石头之后,下一个硬石头之前,第j列,上一个硬石头之后,下一个硬石头之前,不能再次放置炸弹. 首先,这个题,一看 ...