• 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写)。

    以下是相关类定义:

      1 using System;
      2 using System.Collections.Generic;
      3 
      4 namespace ConcurrencySolution
      5 {
      6     #region base classes
      7     public class Msg
      8     {
      9         public string ID
     10         {
     11             get { return _id; }
     12         }
     13         private string _id;
     14 
     15         public Msg()
     16         {
     17             _id = Guid.NewGuid().ToString("N");
     18         }
     19     }
     20 
     21     public class MsgRep
     22     {
     23         public string MsgID;
     24 
     25         public bool ExecResult;
     26 
     27         public MsgRep()
     28             : this(string.Empty, false)
     29         { }
     30 
     31         public MsgRep(string vMsgID, bool vExecResult)
     32         {
     33             MsgID = vMsgID;
     34             ExecResult = vExecResult;
     35         }
     36     }
     37 
     38     public abstract class Chain
     39     {
     40         public Chain Next
     41         {
     42             get { return _next; }
     43         }
     44         private Chain _next;
     45 
     46         public void SetNext(Chain next)
     47         {
     48             _next = next;
     49         }
     50 
     51         public MsgRep HandleMsg(Msg msg)
     52         {
     53             MsgRep rep = HandleMessage(msg);
     54             if (true == rep.ExecResult)
     55                 return rep;
     56 
     57             if (Next != null)
     58                 return Next.HandleMsg(msg);
     59 
     60             return null;
     61         }
     62 
     63         protected abstract MsgRep HandleMessage(Msg msg);
     64     }
     65 
     66     public abstract class Worker : Chain
     67     {
     68         public string WorkerID
     69         {
     70             get { return _workerID; }
     71         }
     72         protected string _workerID;
     73 
     74         protected Worker()
     75             : this(string.Empty)
     76         { }
     77 
     78         protected Worker(string vWorkerID)
     79         {
     80             _workerID = vWorkerID;
     81         }
     82 
     83         protected override MsgRep HandleMessage(Msg msg)
     84         {
     85             WorkerMsg wmsg = msg as WorkerMsg;
     86             if (null == wmsg)
     87                 throw new ArgumentException("isn't a valid WorkerMsg", "msg");
     88 
     89             var rep = DoWork(wmsg);
     90             return rep;
     91         }
     92 
     93         protected abstract WorkerMsgRep DoWork(WorkerMsg msg);
     94     }
     95     #endregion
     96 
     97     public class WorkerMsg : Msg
     98     {
     99         public string Action
    100         {
    101             get { return _action; }
    102         }
    103         private string _action;
    104 
    105         public WorkerMsg(string vAction)
    106             : base()
    107         {
    108             _action = vAction;
    109         }
    110     }
    111 
    112     public class WorkerMsgRep : MsgRep
    113     {
    114         public string WorkerID;
    115 
    116         public WorkerMsgRep()
    117             : this(string.Empty, false, string.Empty)
    118         { }
    119 
    120         public WorkerMsgRep(string vMsgID, bool vExecResult, string vWorkerID)
    121             : base(vMsgID, vExecResult)
    122         {
    123             WorkerID = vWorkerID;
    124         }
    125     }
    126 
    127     #region Workers
    128     public class WorkerJ : Worker
    129     {
    130         public int MentionTimes
    131         {
    132             get { return _mentionTimes; }
    133         }
    134         protected int _mentionTimes;
    135 
    136         protected WorkerJ()
    137             : base()
    138         { }
    139 
    140         public WorkerJ(string vWorkerID)
    141             : base(vWorkerID)
    142         { }
    143 
    144         protected override WorkerMsgRep DoWork(WorkerMsg msg)
    145         {
    146             WorkerMsgRep rep = new WorkerMsgRep(msg.ID, false, WorkerID);
    147             rep.ExecResult = msg.Action == "J";
    148             if (true == rep.ExecResult)
    149                 _mentionTimes++;
    150 
    151             return rep;
    152         }
    153 
    154         public virtual void ChangeWorkerID(string vWorkerID)
    155         {
    156             throw new NotImplementedException();
    157         }
    158     }
    159 
    160     public class WorkerM : Worker
    161     {
    162         public WorkerM(string vWorkerID)
    163             : base(vWorkerID)
    164         { }
    165 
    166         protected override WorkerMsgRep DoWork(WorkerMsg msg)
    167         {
    168             var rep = new WorkerMsgRep(msg.ID, false, WorkerID);
    169             if (msg.Action == "M")
    170                 rep.ExecResult = true;
    171 
    172             return rep;
    173         }
    174     }
    175 
    176     public class WorkerB : Worker
    177     {
    178         public List<DateTime> MentionTime
    179         {
    180             get { return _mentionTime; }
    181         }
    182         List<DateTime> _mentionTime;
    183 
    184         public WorkerB(string vWorkerID)
    185             : base(vWorkerID)
    186         {
    187             _mentionTime = new List<DateTime>();
    188         }
    189 
    190         protected override WorkerMsgRep DoWork(WorkerMsg msg)
    191         {
    192             WorkerMsgRep rep = new WorkerMsgRep(msg.ID, false, WorkerID);
    193             rep.ExecResult = msg.Action == "B";
    194             if (true == rep.ExecResult)
    195                 _mentionTime.Add(DateTime.Now);
    196 
    197             return rep;
    198         }
    199 
    200 
    201     }
    202     #endregion
    203 }
    View Code

    以下是使用:

            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 = 0;
                WorkerMsg ms;
                WorkerMsgRep mr;
                for (int i = 0; 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[0].ToString("HH:mm:ss:ms");
                string time2 = wb.MentionTime[1].ToString("HH:mm:ss:ms");
                ;
            }
    View Code

    例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);
            }
        }
    View Code

      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;
            }
    
        }
    View Code

    方式二,使用举例。

    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,一定要听!

  • 相关阅读:
    CompletionService--实现并行获取future.get()结果
    ConcurrentHashMap+FutureTask实现高效缓存耗时较长的业务结果获取
    Exchanger--线程执行过程中交换数据
    线程池的处理流程
    CyclicBarrier--栅栏,挡住指定数量线程后一次放行
    Semaphore--信号量,控制并发线程数,如流量控制
    CountDownLatch---多线程等待
    线程安全相关概念
    SimpleDateFormat非线程安全
    记java.lang.NoSuchMethodError错误解决过程
  • 原文地址:https://www.cnblogs.com/xuanhu/p/10459407.html
Copyright © 2020-2023  润新知