1.单例模式

单例模式恐怕是很多开发人员最先接触到的模式之一,可以认为就是一个全局变量。它的初始化过程无非就是一开始就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;
}
}
}

2.责任链模式

在一些情况下,对一个消息(含事件)的响应和处理需要很多对象来参与,这些对象对消息的处理有前后顺序,形成一个处理链条,但对象是否真正处理消息有赖于在它之前的对象的处理策略,前一个对象处理后,后一个对象则不需参与处理,这就是责任链模式。现实中有很多类似的场景,比如上访,上访一般是从最基层的信访部门接受信访开始进行处理,如果下一级信访部门无法处理,则交给上一级部门进行处理,这样一级一级的处理,知道最高信访部门。这样所有层级的信访部门就构成了一个责任链。

责任链模式在设计中的应用很多,比如Delphi中对系统对消息的处理,对异常的处理等。只是建立责任链的方式可能不同,有的是建立明确的处理责任链,如消息处理一般是根据控件的Parent来建立责任链条;有的则是暗含一种处理机制,比如Delphi的异常处理(C#也类似)总是从最内层到外,从被调用对象到调用对象这条链进行。

简单责任链模式示例:

public abstract class Chain_Successor
{
protected Chain_Successor successor; //保存后继责任者的引用
/// <summary>
/// 处理需求
/// </summary>
/// <param name="request">需要处理的类</param>
public abstract void HandleReqest(Chain_Request request);
/// <summary>
/// 设置后继责任者
/// </summary>
/// <param name="successor">后继责任者</param>
public void SetChain_Successor(Chain_Successor successor)
{
this.successor = successor;
}
}
public class Chain_ConcreateHandleA : Chain_Successor
{
public Chain_ConcreateHandleA()
{
}
public override void HandleReqest(Chain_Request request)
{
//如果自己能处理则处理,否则传递给后继者
if(request.Request_Type==)
{
System.Windows.Forms.MessageBox.Show(this.ToString()+":"+request.Request_Parameters);
}
else
{
if(this.successor!=null)
successor.HandleReqest(request);
}
} }
public class Chain_ConcreateHandleB : Chain_Successor
{
public Chain_ConcreateHandleB()
{
}
public override void HandleReqest(Chain_Request request)
{
//如果自己能处理则处理,否则传递给后继者
if(request.Request_Type==)
{
System.Windows.Forms.MessageBox.Show(this.ToString()+":"+request.Request_Parameters);
}
else
{
if(this.successor!=null)
successor.HandleReqest(request);
}
} }
public class Chain_ConcreateHandleC : Chain_Successor
{
public Chain_ConcreateHandleC()
{
}
public override void HandleReqest(Chain_Request request)
{
//如果自己能处理则处理,否则传递给后继者
if(request.Request_Type==)
{
System.Windows.Forms.MessageBox.Show(this.ToString()+":"+request.Request_Parameters);
}
else
{
if(this.successor!=null)
successor.HandleReqest(request);
}
} }
public class Chain_Request
{
//下面的两个参数可更加具体需要进行构造
private int _Request_type;
private string _Request_parameters;
public Chain_Request(int Request_type,string RequestParameters)
{
this._Request_type = Request_type;
this._Request_parameters = RequestParameters;
}
public int Request_Type
{
get
{
return _Request_type;
}
set
{
_Request_type = value;
}
}
public string Request_Parameters
{
get
{
return _Request_parameters;
}
set
{
_Request_parameters = value;
}
}
}
public class Chain_Client
{
public static void Test()
{
Chain_Successor firstHandler = new Chain_ConcreateHandleA();
Chain_Successor secondHandler = new Chain_ConcreateHandleB();
Chain_Successor ThirdHandler = new Chain_ConcreateHandleC();
firstHandler.SetChain_Successor(secondHandler);
secondHandler.SetChain_Successor(ThirdHandler);
firstHandler.HandleReqest(new Chain_Request(,"hello,the world!"));
}
}

3.简单工厂模式

角色:用户,工厂,产品

目的是使得用户将产品的消费和生产分开.在编程中就是将类的创建和使用分开.从而达到责任分离,其实这也是所有创建模式的目的之一.做法是工厂类根据用户的要求(参数)来返回不同的类的实例.

工厂实现:采用参数化的静态方法为用户提供类实例的创建,如下所示:

public static ProductType FactoryMethod(参数)

{

根据参数返回需要类的实例.

}

简单工厂有几种情况:

1.产品只有一种,这种情况下方法没必要带参数.

2.产品有多种,且属于同类型产品,则可以加入抽象产品.加入抽象产品的一个潜在好处是可以让用户可以不关心具体的产品,在设计和实现上可以做到一定程度上的延后联编.

3.产品有多种,且类型各异,则可以考虑采用其它模式或者提供多个工厂方法来实现.但不鼓励采用后者来实现(做事要专业).

4.在实际应用中产品角色,工厂角色以及用户角色都可以根据实际情况合并.(模式变形)

简单工厂模式的理解:

1.如果产品创建的时候需要用户提供指导,则简单工厂模式不适合,如果要适用就会使得工厂方法的参数过于复杂,因此本模式只适合用户不关心产品构造逻辑,只关心使用的情况下(不关心构建,只关心使用).

2.大多数情况下用户还是必须知道产品的具体细节,没有减少对细节的依赖(特殊情况,有抽象产品的情况下,在某些应用中可以减少对具体产品的细节依赖).

3.采用静态方法实现类的创建,好处是可以减少工厂类本身的创建,但缺点是失去了工厂类进行继承扩展的优点.

4.简单工厂模式的好处是实现了责任分离,对用户来讲同时也隐藏了构建产品的细节,而且实现起来比较简单.

5.增加产品的时候,工厂类需要修改,也违背了面向对象的开放封闭原则.

6.只适合产品类比较少的情况,如果产品类太多,会使得静态工厂方法过于庞大.

但现在有一种比较简单的办法,就是采用反射或者泛型来规避静态方法过多而使得工厂类庞大的问题.

4.观察者模式

观察者设计模式定义了对象间的一种一对多的依赖关系,以便一个对象的状态发生变化时,所有依赖于它的对象都得到通知并自动刷新。在现实生活中的可见观察者模式,例如,微信中的订阅号,订阅博客和QQ微博中关注好友,这些都属于观察者模式的应用。

实现:比如热水器在烧水的过程中,当水温即将烧开时,会发出报警的声音,显示器上会出现温度监控

public interface IObserver
{
/// <summary>
/// 更新自身状态
/// </summary>
void Update(int temp);
}
/// <summary>
/// IObserverable接口
/// </summary>
public interface IObservable
{
/// <summary>
/// 注册IObserver
/// </summary>
/// <param name="obj"></param>
void Register(IObserver obj);
/// <summary>
/// 取消IObserver的注册
/// </summary>
/// <param name="obj"></param>
void Unregister(IObserver obj);
}
// <summary>  

/// 抽 象基类
/// </summary>
public abstract class SubjectBase:IObservable
{
private List<IObserver> container = new List<IObserver>();
public void Register(IObserver obj)
{
container.Add(obj);
}
public void Unregister(IObserver obj)
{
container.Remove(obj);
}
/// <summary>
/// 通知所有注册了的Observe
/// </summary>
protected virtual void Notify(int temp)
{
foreach (IObserver observer in container)
{
//调用Observer的Update()方法
observer.Update(temp);
}
}
}
public class Heater:SubjectBase
{
private int temp;//水温
protected virtual void OnBioiled()
{
base.Notify(temp);
}
public void GetMonitoring()
{
for (int i = ; i <= ; i++)
{
temp = i + ;
if (temp > )
{
OnBioiled();
}
}
}
}
public class Alarm:IObserver
{
public void Update(int temp)
{
if (temp == )
{
Console.WriteLine("水烧开了"+temp);
}
else
{
Console.WriteLine("开始报警,水快烧开了>> " + temp);
}
}
}
public class Screen:IObserver
{
public void Update(int temp)
{
if (temp == )
{
Console.WriteLine("水烧开了" + temp);
}
else
{
Console.WriteLine("水快烧开了>> " + temp);
}
}
}
/// <summary>
/// C#设计模式-观察者模式
/// </summary>
class Program
{
static void Main(string[] args)
{
Heater heater = new Heater();
heater.Register(new Screen());
heater.Register(new Alarm());
heater.GetMonitoring();
}
}
  1. 在上面的例子中,热水器是Subject,报警器和显示器是Observer,报警器和显示器关心热水器中的水温。

    优点:
    观察者模式实现了表示层和数据逻辑层的分离,并定义了稳定的更新消息传递机制,并抽象了更新接口,使得可以有各种各样不同的表示层,即观察者。
    观察者模式在被观察者和观察者之间建立了一个抽象的耦合,被观察者并不知道任何一个具体的观察者,只是保存着抽象观察者的列表,每个具体观察者都符合一个抽象观察者的接口。
    观察者模式支持广播通信。被观察者会向所有的注册过的观察者发出通知。
    缺点:
    如果一个被观察者有很多直接和间接的观察者时,将所有的观察者都通知到会花费很多时间。
    虽然观察者模式可以随时使观察者知道所观察的对象发送了变化,但是观察者模式没有相应的机制使观察者知道所观察的对象是怎样发生变化的。
    如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃,在使用观察者模式应特别注意这点。

    观察者模式定义了一种一对多的依赖关系,让多个观察者对象可以同时监听某一个主题对象,这个主题对象在发生状态变化时,会通知所有观察者对象,使它们能够自动更新自己,解决的是“当一个对象的改变需要同时改变多个其他对象”的问题。

C#常用设计模式的更多相关文章

  1. Android常用设计模式(二)

    Android常用设计模式之观察者模式 观察者设计模式在Android应用中会经常用到,模式原理类似于这样的场景: 用户订报纸,然后在报社登记,报社来统计用户(添加用户),用户也可以取消订阅,报社删除 ...

  2. 代码重构 & 常用设计模式

    代码重构 重构目的 相同的代码最好只出现一次 主次方法 主方法 只包含实现完整逻辑的子方法 思维清楚,便于阅读 次方法 实现具体逻辑功能 测试通过后,后续几乎不用维护 重构的步骤 1  新建一个方法 ...

  3. IOS开发常用设计模式

    IOS开发常用设计模式 说起设计模式,感觉自己把握不了笔头,所以单拿出iOS开发中的几种常用设计模式谈一下. 单例模式(Singleton) 概念:整个应用或系统只能有该类的一个实例 在iOS开发我们 ...

  4. python之路,Day24 常用设计模式学习

    python之路,Day24 常用设计模式学习   本节内容 设计模式介绍 设计模式分类 设计模式6大原则 1.设计模式介绍 设计模式(Design Patterns) --可复用面向对象软件的基础 ...

  5. java常用设计模式总览

    一.java的设计模式大体上分为三大类: 创建型模式(5种):工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式. 结构型模式(7种):适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组 ...

  6. javaEE Design Patter(1)初步了解23种常用设计模式

    设计模式分为三大类: 创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. 结构型模式,共七种:适配器模式.装饰器模式.代理模式.外观模式.桥接模式.组合模式.享元模式. ...

  7. PHP 进阶篇:面向对象的设计原则,自动加载类,类型提示,traits,命名空间,spl的使用,反射的使用,php常用设计模式 (麦子学员 第三阶段)

    以下是进阶篇的内容:面向对象的设计原则,自动加载类,类型提示,traits,命名空间,spl的使用,反射的使用,php常用设计模式 ================================== ...

  8. C++源码实现:21种常用设计模式

    C++源码实现:21种常用设计模式一直以来在设计模式的学习中,都是出现java的源码,这对学习C++的极度不友好.本工程是基于C++实现21种常用的设计模式,里面包含了实例代码和示例.编写的时候在学习 ...

  9. 23种常用设计模式的UML类图

    23种常用设计模式的UML类图 本文UML类图参考<Head First 设计模式>(源码)与<设计模式:可复用面向对象软件的基础>(源码)两书中介绍的设计模式与UML图. 整 ...

  10. 7 种 Javascript 常用设计模式学习笔记

    7 种 Javascript 常用设计模式学习笔记 由于 JS 或者前端的场景限制,并不是 23 种设计模式都常用. 有的是没有使用场景,有的模式使用场景非常少,所以只是列举 7 个常见的模式 本文的 ...

随机推荐

  1. rookit入門

    来源:rootkit_com 作者:Clandestiny 翻译:fqh “Help!我是一名新手!我需要一款rootkit入侵朋友的机器…我想编写自己的rootkit…我想开始开发代码… 该从哪里入 ...

  2. docker--image的获取

    image有几种获取方式: 1.Docker官方提供了一种文件格式:Dockerfile,通过这种格式的文件,我们可以定义一个image,然后通过Dockerfile我们可以构建(build)一个im ...

  3. Inversion of Control 控制反转 有什么好处

    作者:Mingqi链接:https://www.zhihu.com/question/23277575/answer/169698662来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转 ...

  4. 一文读懂MQTT协议

    1  概述 MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的"轻量级 ...

  5. java 中String类的常用方法总结,玩转String类

    String类: String类在java.lang包中,java使用String类创建一个字符串变量,字符串变量属于对象.String类对象创建后不能修改,StringBuffer & St ...

  6. HDU-6532 Chessboard 2019广东省省赛B题(费用流)

    比赛场上很容易想到是费用流,但是没有想到建图方法qwq,太弱了. 这里直接贴官方题解: 费用流.离散化坐标,每行用一个点表示,每列也用一个点表示.表示第i-1行的点向表示第i行的点连边,容量为第i行及 ...

  7. Codeforces 1105E 最大独立集 状态DP 中途相遇法

    题意:你有一个字符串, 有两种操作,一种是改变字符串,一种是某个用户询问这个字符串,如果一个用户每次查询字符串的时候都是他的用户名,他就会高兴.问最多有多少个用户会高兴? 题意:容易发现,在两个1操作 ...

  8. app混合开发 fastlick.js 在ios上 input标签点击 不灵敏 处理

    ios11 上有这个问题 而老版本的ios没有 会出现这个的原因是使用fastclick.js点击后input没有获取焦点,所以只需要在fasyclick的源码的这个位置 可以直接在源码内搜索关键字找 ...

  9. vue搭建vue-cli脚手架项目

    一.Node.js 1.介绍 Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine.Node.js是一个基于Ch ...

  10. Java中的LinkedHashSet