C#项目中常用到的设计模式

1. 引言

一个项目的通常都是从Demo开始,不断为项目添加新的功能以及重构,也许刚开始的时候代码显得非常凌乱,毫无设计可言。但是随着项目的迭代,往往需要将很多相同功能的代码抽取出来,这也是设计模式的开始。熟练运用设计模式应该是每一个软件开发人员的必备技能。今天给大家介绍几个常用的设计模式。

2. 单例模式

单例模式恐怕是很多开发人员最先接触到的模式之一,可以认为就是一个全局变量。它的初始化过程无非就是一开始就new 一个instance,或者惰性初始化等需要用到的时候new 一个instance。这里需要注意的是在多线程情况下new一个instance。通常加上lock 可以解决问题。这里我们利用C# 的系统函数 Interlocked.CompareExchange

    internal class SingletonOne
    {
        private static SingletonOne _singleton;
        private SingletonOne()
        {
        }

        public static SingletonOne Instance
        {
            get
            {
                if (_singleton == null)
                {
                    Interlocked.CompareExchange(ref _singleton, new SingletonOne(), null);
                }

                return _singleton;
            }
        }
    }

3. 迭代器模式

迭代器模式也是用的比较多的一种,通常见于C#的内置容器数据结构 List,Stack等等,为了便于遍历容器内元素。这里给出一个简单版的Stack实现

    internal class Stack<T> : IEnumerable<T>, IEnumerable
    {
        private T[] _array;
        private int _index;
        private const int DefaultSize = 4;

        public Stack(int size)
        {
            var sized = size > 0 ? size : DefaultSize;
            this._array = new T[sized];
            this._index = 0;
        }

        public int Count
        {
            get { return this._index; }
        }

        public Stack(IEnumerable<T> data) : this(0)
        {
            var enumrator = data.GetEnumerator();
            while (enumrator.MoveNext())
            {
                var item = enumrator.Current;
                this.Push(item);
            }
        }

        public void Push(T item)
        {
            if (this._index < this._array.Length)
            {
                this._array[this._index++] = item;
            }
            else
            {
                var newLength = this._array.Length << 1;
                T[] newArray = new T[newLength];
                Array.Copy(this._array, newArray, this.Count);

                this._array = newArray;
                this.Push(item);
            }
        }

        public T Pop()
        {
            if (this.Count <= 0)
            {
                throw new ArgumentOutOfRangeException("pop");
            }
            else
            {
                this._array[this._index] = default(T);
                return this._array[--this._index];
            }
        }

        public T Get(int index)
        {
            if (this.Count <= index)
            {
                throw new ArgumentOutOfRangeException("Get");
            }
            else
            {
                return this._array[index];
            }
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }

        public IEnumerator<T> GetEnumerator()
        {
            return new StackEnumerator<T>(this);
        }
    }

Stack 的 迭代器内部实现:

    internal class StackEnumerator<T> : IEnumerator<T> , IEnumerator
    {
        private Stack<T> _stack;
        private int _index;

        public StackEnumerator(Stack<T> stack)
        {
            this._stack = stack;
            this._index = -1;
        }

        public bool MoveNext()
        {
            this._index++;
            return this._index < this._stack.Count;
        }

        public void Reset()
        {
            this._index = -1;
        }

        object  IEnumerator.Current
        {
            get { return this.Current; }
        }

        public T Current
        {
            get { return this._stack.Get(this._index); }
        }

        public void Dispose()
        {
            this._stack = null;
        }
    }

4 工厂模式

工厂模式细分的话有简单工厂模式、抽象工厂模式等。它最核心的就是如何通过 Factory new 一个 对象出来。在ASP.NET MVC 消息处理实现过程中工厂模式运用的非常多。比如

在MVC中处理一个Request,其实就是调用Controller下的一个Action,这就需要从Url 和Route 中反射出Controller对象,内部由ControllerFactory创建。

它的默认实现是:DefaultControllerFactory

另一个例子是ValueProviderFactory,它使得Controller 下的Action 能够接收到前端传回来的数据并实现模型绑定,是典型的抽象工厂实现。

5. 订阅模式

订阅模式在某些项目运用比较多,比如 Knockout 整个项目就是一个大的订阅模式的实现,但是它是用javascript编写的。还有像微博、微信公众号等等订阅模式通常少不了。

通常可以定义接口:

    internal interface ISubject
    {
        IEnumerable<IObserver> Observers { get; }
        void Notify();
        void AddObserver(IObserver observer);
        void RemoveObserver(IObserver observer);
    }

    internal interface IObserver
    {
        void ReceiveSubject(ISubject subject);
    }

实现:

    internal class AritcleObserver : IObserver
    {
        public void ReceiveSubject(ISubject subject)
        {
            // receive the subject
        }
    }

    class WeChatArticle : ISubject
    {
        private ICollection<IObserver> _observers;
        private string _name;

        public WeChatArticle(string name)
        {
            this._name = name;
            this._observers = new List<IObserver>();
        }

        public IEnumerable<IObserver> Observers
        {
            get { return this._observers; }
        }

        public void Notify()
        {
            foreach (IObserver observer in this._observers)
            {
                observer.ReceiveSubject(this);
            }
        }

        public void AddObserver(IObserver observer)
        {
            this._observers.Add(observer);
        }

        public void RemoveObserver(IObserver observer)
        {
            this._observers.Remove(observer);
        }
    }

6.  责任链模式

责任链模式没有像工厂模式那样被人熟悉,在ASP.NET WebApi 中有一个非常典型的实现 就是WebApi的消息处理管道HttpMessageHandler

这里给一个简单的模拟

    class DataRequest
    {
        public string FileName { get; set; }
    }

    class DataResponse
    {
        public string Error { get; set; }
        public string Data { get; set; }
    }

    internal abstract class RequestHandler
    {
        public RequestHandler NextHandler { get; set; }
        public abstract DataResponse Process(DataRequest request);
    }

    class ReadRequestHandler : RequestHandler
    {
        public override DataResponse Process(DataRequest request)
        {
            return new DataResponse()
            {
                Data = File.ReadAllText(request.FileName)
            };
        }
    }

    class ExistsRequestHandler : RequestHandler
    {
        public override DataResponse Process(DataRequest request)
        {
            if (File.Exists(request.FileName))
            {
                return this.NextHandler.Process(request);
            }
            else
            {
                return new DataResponse()
                {
                    Error = "no exists"
                };
            }
        }
    }

7. 组合模式

组合模式是使得单个对象和组合对象有一致的行为,一致的行为可以理解为拥有同一个接口,比如图形显示

    class ControlContext
    {
    }

    internal interface IControl
    {
        void Draw(ControlContext context);
    }

    class Line : IControl
    {
        public void Draw(ControlContext context)
        {
        }
    }

    class Circle : IControl
    {
        public void Draw(ControlContext context)
        {}
    }

    class CompositeControl : IControl
    {
        private List<IControl> controls;

        public CompositeControl(IList<IControl> cons)
        {
            this.controls = new List<IControl>(cons);
        }

        public void Draw(ControlContext context)
        {
            this.controls.ForEach(c => c.Draw(context));
        }

        public void Add(IControl control)
        {
            this.controls.Add(control);
        }
    }

8. 总结

市场上有很多关于设计模式的书,但是基本的设计模式大概有20多种,本文给大家介绍了几种项目中常见的设计模式,其实有些设计模式在实际项目已经不知不觉用起来了。

以后再给大家介绍其他的几种设计模式。

欢迎访问我的个人主页 51zhang.net  网站还在不断开发中…..

时间: 2024-10-07 14:56:07

C#项目中常用到的设计模式的相关文章

项目中常用的SQL语句

摘要: 对于像我一样的菜鸟级别人物来说,接触的项目比较少,平常做的那些练习,包括三层中,一般也只能用到增删改查,当然这些增删改查语句是学数据库语句的入门,在百度上搜索一大堆,w3cschool中帮助文档也可以查阅. 这里是把平常用的增删改做一个小小总结,对一些小小项目也是比较适用的 ,当然,好记性不如烂笔头吗,这个时代纸质版的笔记感觉很欠缺,因为想要看的时候,你得找到那本书,而且要翻翻在哪里,感觉很不方便.并且电子版 的随便copy之类的都可以. 常用的sql语句(增删改查) 1.增加.插入语句

简析项目中常用的七参数转换法和四参数转换法以及涉及到的基本测量学知识

1.背景 在了解这两种转换方法时,我们有必要先了解一些与此相关的基本知识.我们有三种常用的方式来表示空间坐标,分别是:经纬度和高层.平面坐标和高层以及空间直角坐标. 2.经纬度坐标系(大地坐标系) 这里我首先要强调:天文坐标表示的经纬度和大地坐标系表示的经纬度是不同的.所以,同一个经纬度数值,在BJ54和WGS84下表示的是不同的位置,而以下我说的经纬度均指大地坐标系下的经纬度.大地坐标系是大地测量中以参考椭球面为基准面建立起来的坐标系.下面我跟大家大致谈谈其中涉及到的两个重要概念. 2.1大地

iOS项目中常用的第三方开源库

1.项目使用的第三方开源库 http://github.ibireme.com/github/list/ios/整理了比较常用的iOS第三方组件,以及github上的统计. 项目使用了CocoaPods(类似java中的maven)管理常用的第三方库,一些特殊的单独引用,下面介绍下比较好用的几个. (1)AFNetworking 目前比较推荐的iOS网络请求组件,默认网络请求是异步,通过block回调的方式对返回数据进行处理. 需要注意的是AFNetworking对服务器返回的ContentTy

Swift 项目中常用的第三方框架

Swift 项目中可能用到的第三方框架 字数1004 阅读4091 评论17 喜欢93 这里记录下swift开发中可能用的框架 , 最近浏览了不少,积累在这里,以后用的时候方便查阅.顺便推荐给大家! 这里的框架都是纯swift的 , 感谢开源 ,感谢大神们 . 下拉刷新 BreakOutToRefresh 一个下拉刷新打砖块的swift库 SDRefreshView 简单易用的上拉和下拉刷新 ZLSwiftRefresh - 下拉刷新/上拉加载更多,支持自定义动画,集成简单 GearRefres

项目中常用SQL语句总结

1.项目中常常需要修改字段长度,但需要保留数据--增加业务受理 项目名称 字段长度alter table t_ywsl add aa varchar2(200);update t_ywsl set aa=proname,proname=null;commit;alter table t_ywsl modify proname varchar2(200);update t_ywsl set proname=aa,aa=null;commit;alter table t_ywsl drop colu

项目中常用到思科的模块

思科的模块有很多,在项目中经常用到的有以下几种.一.千兆模块1.千兆单模模块大体样式如下图:GLC-LH-SMD:单模10KM模块,工作温度-5°C to 85°C .GLC-EX-SMD:单模40KM模块,工作温度-5°C to 85°C .GLC-ZX-SMD:单模70KM模块,工作温度-5°C to 85°C .2.千兆多模模块GLC-SX-MMD:多模模块,工作温度-5°C to 85°C .3.千兆光转电模块GLC-T:光口转电口,工作温度0 to 70°C.大体样式如下图:二.万兆模

ssm项目中常用的上传文件

在项目中,上传文件一般是必不可少的,所以今天学到新的上传方式,就干脆将学习过的上传方式记录一下 一.表单直接上传图片 表单头要设置 <form action="" method="post" enctype="multipart/form-data"> 元素 <input type="file" name="dwfile" > 后端代码 @RequestMapping(value=&

项目中常用的设计模式

本文为博主原创,允许转载,但请声明原文地址:http://www.coselding.cn/blog/4/4-117.html 业务代表模式:(相同接口的不同实现的查询选择方式) 步骤: 业务接口: 业务接口实现,多个: 业务接口实现的查询类,根据关键字查询相应的接口实现类: 业务代表:维护一个业务查询类和一个业务接口引用,关键字设置,执行方法中根据关键字获得业务实现类的引用,并使用业务执行相应的功能: 业务发出者通过业务代表即可实现相应的业务处理,需要实现设置关键字. 组合实体模式:(复杂实体

从真实项目中抠出来的设计模式——第三篇:责任链模式

一:现实场景 有时候在开发的过程中,我们经常会根据某个状态的值,写出很多的ifelse逻辑,比如拿项目里面的案例来说,如果当前发送的是彩信,此种状态需要如何给 实体赋值,如果是短信,邮件又是其他方式的赋值,等等此类,这种情况下一般会写出如下if判断,对吧,真实代码如下: 1 if (leaflet.CommunicationtypeEnum.HasFlag(CommunicationTypeEnum.邮件)) 2 { 3 //第三步:动态生成邮件模板 4 var styleInfo = Cach