在上一篇文章里我通过具体场景总结了“.net面向对象的设计原则”,其中也多次提到一些设计模式方面的技术,可想而知,设计模式在我们的开发过程中也是必不可少的。今天我们就来简单交流下设计模式。对于设计模式的介绍呢,网上流行这么一句话“想要搞好对象,必须要熟知套路”,所以百度中说设计模式简介时“设计模式一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结”一点也没错,在开发过程中通过渗入一些设计模式,我们的设计效果又会怎么样呢?话不多说,直接进入正题吧!

一、设计模式的分类

GOF一共总结了23套设计模式,大致可以分为以下三类:

  • 创造型模式

这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象。这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活,该类型包括:单件模式、抽象工厂、建造者模式、工厂方法模式和原型模式等5种。

  • 结构型模式

这些设计模式关注类和对象的组合。继承的概念被用来组合接口和定义组合对象获得新功能的方式,该类型包括:适配器模式、桥接模式、组合模式、装饰模式、外观模式、享元模式和代理模式等7种。

  • 行为型模式

这些设计模式特别关注对象之间的通信。分为职责链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法、访问者模式等11种。

二、设计模式解析

常用设计模式浅析:

1、单件模式

结构图 :     

意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

适用性

  • 当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。
  • 当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。

示意性代码

     //单件模式示意性代码
public class Singleton
{
//创建私有对象,保证只有一个对象
private static Singleton _instance; //保护类型的构造函数,子类化可扩展
protected Singleton() { } //提供公共访问点
public static Singleton Instance()
{ // 使用 'Lazy initialization',为对象实例化
if (_instance == null)
{
_instance = new Singleton();
} return _instance;
}
}

Singleton

特点总结:实例对外唯一、子类可以扩展并且提供 一个公共的访问点访问。

实际应用

     /// <summary>
/// 投票选举
/// </summary>
public class LoadBalancer
{
//实例唯一
private static LoadBalancer instance;
//选举人
private ArrayList servers = new ArrayList();
//随机数
private Random random = new Random();
//用于异步
private static object syncLock = new object();
//保护构造函数,创建时添加选举人
protected LoadBalancer()
{
servers.Add("ServerI");
servers.Add("ServerII");
servers.Add("ServerIII");
servers.Add("ServerIV");
servers.Add("ServerV");
}
//公共访问点,初始化投票对象
public static LoadBalancer GetLoadBalancer()
{
if (instance == null)
{
lock (syncLock)
{
if (instance == null)
{
instance = new LoadBalancer();
}
}
} return instance;
}
public string Server
{
get
{
int r = random.Next(servers.Count);
return servers[r].ToString();
}
}
}

LoadBalancer

   public class SingletonMain
{
static void Main()
{
LoadBalancer b1 = LoadBalancer.GetLoadBalancer();
LoadBalancer b2 = LoadBalancer.GetLoadBalancer();
LoadBalancer b3 = LoadBalancer.GetLoadBalancer();
LoadBalancer b4 = LoadBalancer.GetLoadBalancer(); if (b1 == b2 && b2 == b3 && b3 == b4)
{
Console.WriteLine("Same instance\n");
} // Load balance 15 server requests
for (int i = ; i < ; i++)
{
Console.WriteLine(b1.Server);
} Console.ReadKey();
}
}

SingletonMain

2、抽象工厂

结构图:

意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

适用性 :

  • 个系统要独立于它的产品的创建、组合和表示时。
  • 一个系统要由多个产品系列中的一个来配置时。
  • 当你要强调一系列相关的产品对象的设计以便进行联合使用时。
  • 当你提供一个产品类库,而只想显示它们的接口而不是实现时

示意性代码

     public abstract class AbstractFactory
{
public abstract AbstractProductA CreateProductA();
public abstract AbstractProductB CreateProductB();
}
public abstract class AbstractProductA { }
public abstract class AbstractProductB
{
public abstract void Interact(AbstractProductA a);
}
public class ConcreteFactory1 : AbstractFactory
{
public override AbstractProductA CreateProductA()
{
return new ProductA1();
}
public override AbstractProductB CreateProductB()
{
return new ProductB1();
}
}
public class ConcreteFactory2 : AbstractFactory
{
public override AbstractProductA CreateProductA()
{
return new ProductA2();
}
public override AbstractProductB CreateProductB()
{
return new ProductB2();
}
}
public class ProductA1 : AbstractProductA { }
public class ProductA2 : AbstractProductA { }
public class ProductB1 : AbstractProductB
{
public override void Interact(AbstractProductA a)
{
Console.WriteLine(this.GetType().Name + " interacts with " +
a.GetType().Name);
}
}
public class ProductB2 : AbstractProductB
{
public override void Interact(AbstractProductA a)
{
Console.WriteLine(this.GetType().Name + " interacts with " +
a.GetType().Name);
}
}

AbstractFactory

    public class Client
{
private AbstractProductA _abstractProductA;
private AbstractProductB _abstractProductB; // Constructor
public Client(AbstractFactory factory)
{
_abstractProductB = factory.CreateProductB();
_abstractProductA = factory.CreateProductA();
} public void Run() => _abstractProductB.Interact(_abstractProductA);
}

Client

    class AbstractFactoryMain
{
public static void Main()
{
// Abstract factory #1
AbstractFactory factory1 = new ConcreteFactory1();
Client c1 = new Client(factory1);
c1.Run(); // Abstract factory #2
AbstractFactory factory2 = new ConcreteFactory2();
Client c2 = new Client(factory2);
c2.Run(); Console.ReadKey();
}
}

AbstractFactoryMain

特点总结:抽象,多态,一系列相关关联。

3、代理模式

结构图:

意图:为其他对象提供一种代理以控制对这个对象的访问。

适用性 :

  • 在需要用比较通用和复杂的对象指针代替简单的指针的时候,使用 Proxy 模式。

示意性代码

    public abstract class Subject
{
public abstract void Request();
} public class RealSubject : Subject
{
public override void Request()
{
Console.WriteLine("Called RealSubject.Request()");
}
} public class Proxy : Subject
{
RealSubject realSubject; public override void Request()
{
// Use 'lazy initialization'
if (realSubject == null)
{
realSubject = new RealSubject();
} realSubject.Request();
}
}

Proxy

实际应用:

     /// <summary>
/// Subject接口
/// </summary>
public interface IMath
{
//加法操作
double Add(double x, double y);
//减法操作
double Sub(double x, double y);
//乘法操作
double Mul(double x, double y);
//除法操作
double Div(double x, double y);
} /// <summary>
/// 具体实现类
/// </summary>
public class Math : IMath
{
public double Add(double x, double y)
{
return x + y;
}
public double Sub(double x, double y)
{
return x - y;
}
public double Mul(double x, double y)
{
return x * y;
}
public double Div(double x, double y)
{
return x / y;
}
}
/// <summary>
/// 代理类
/// </summary>
public class MathProxy : IMath
{
Math math;
public MathProxy() { math = new Math(); } public double Add(double x, double y) { return math.Add(x, y); }
public double Sub(double x, double y) { return math.Sub(x, y); }
public double Mul(double x, double y) { return math.Mul(x, y); }
public double Div(double x, double y) { return math.Div(x, y); }
}

MathProxy

4、观察者模式

结构图:

意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。

适用性 :

  • 当一个抽象模型有两个方面, 其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用

  • 当对一个对象的改变需要同时改变其它对象, 而不知道具体有多少对象有待改变。

  • 当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之, 你不希望这些对象是紧密耦合的。

示意性代码

     /// <summary>
/// 操作抽象类
/// </summary>
public abstract class Subject
{
//观察者数组
private ArrayList observers = new ArrayList();
//添加观察者
public void Attach(Observer observer) => observers.Add(observer);
//删除观察者
public void Detach(Observer observer) => observers.Remove(observer);
//通知观察者们
public void Notify()
{
foreach (Observer o in observers)
{
o.Update();
}
}
}
/// <summary>
/// 具体操作类
/// </summary>
public class ConcreteSubject : Subject
{
// Property
public string SubjectState { get; set; }
}
/// <summary>
/// 观察者类
/// </summary>
public abstract class Observer
{
//更新
public abstract void Update();
} /// <summary>
/// 具体的观察者
/// </summary>
public class ConcreteObserver : Observer
{
private string name;
private string observerState; // Constructor
public ConcreteObserver(ConcreteSubject subject, string name)
{
this.Subject = subject;
this.name = name;
} public override void Update()
{
observerState = Subject.SubjectState;
Console.WriteLine("Observer {0}'s new state is {1}", name,
observerState);
} // Property
public ConcreteSubject Subject { get; set; }
}

Observer

   实际应用:

     /// <summary>
/// 拍卖类
/// </summary>
public abstract class Stock
{
protected string symbol;
protected double price;
private ArrayList investors = new ArrayList(); public Stock(string symbol, double price)
{
this.symbol = symbol;
this.price = price;
} public void Attach(Investor investor)
{
investors.Add(investor);
}
public void Detach(Investor investor)
{
investors.Remove(investor);
} public void Notify()
{
foreach (Investor investor in investors)
{
investor.Update(this);
}
Console.WriteLine("");
} // Properties
public double Price
{
get
{
return price;
}
set
{
price = value;
Notify();
}
} public string Symbol
{
get
{
return symbol;
}
set
{
symbol = value;
}
}
}
/// <summary>
/// IBM拍卖
/// </summary>
public class IBM : Stock
{
public IBM(string symbol, double price) : base(symbol, price)
{
}
}
/// <summary>
/// 投资商接口
/// </summary>
interface IInvestor { void Update(Stock stock); }
/// <summary>
/// 投资商
/// </summary>
public class Investor : IInvestor
{
private string name; private Stock stock; public Investor(string name)
{
this.name = name;
} public void Update(Stock stock)
{
Console.WriteLine("Notified {0} of {1}'s " + "change to {2:C}", name,
stock.Symbol, stock.Price);
} public Stock Stock
{
get { return stock; }
set { stock = value; }
}
}

ObserverExample

特点总结:抽象,依赖,一个方面依赖于另一方面。

好了,今天就总结到这里了欢迎纠错,谢谢!!!

.net之设计模式的更多相关文章

  1. MVVM设计模式和WPF中的实现(四)事件绑定

    MVVM设计模式和在WPF中的实现(四) 事件绑定 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在WPF中 ...

  2. java EE设计模式简介

    1.何为设计模式 设计模式提供了对常见应用设计问题的解决方案.在面向对象的编程中,设计模式通常在解决与对象创建和交互相关的问题,而非整体软件架构所面对的大规模问题,它们以样板代码的形式提供了通用的解决 ...

  3. 计算机程序的思维逻辑 (54) - 剖析Collections - 设计模式

    上节我们提到,类Collections中大概有两类功能,第一类是对容器接口对象进行操作,第二类是返回一个容器接口对象,上节我们介绍了第一类,本节我们介绍第二类. 第二类方法大概可以分为两组: 接受其他 ...

  4. 《JavaScript设计模式 张》整理

    最近在研读另外一本关于设计模式的书<JavaScript设计模式>,这本书中描述了更多的设计模式. 一.创建型设计模式 包括简单工厂.工厂方法.抽象工厂.建造者.原型和单例模式. 1)简单 ...

  5. 《JavaScript设计模式与开发实践》整理

    最近在研读一本书<JavaScript设计模式与开发实践>,进阶用的. 一.高阶函数 高阶函数是指至少满足下列条件之一的函数. 1. 函数可以作为参数被传递. 2. 函数可以作为返回值输出 ...

  6. 设计模式之行为类模式大PK

                                        行为类模式大PK 行为类模式包括责任链模式.命令模式.解释器模式.迭代器模式.中介者模式.备忘录模式.观察者模式.状态模式.策略 ...

  7. .NET设计模式访问者模式

    一.访问者模式的定义: 表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作. 二.访问者模式的结构和角色: 1.Visitor 抽象访问者角色,为该 ...

  8. Java开发中的23种设计模式详解

    [放弃了原文访问者模式的Demo,自己写了一个新使用场景的Demo,加上了自己的理解] [源码地址:https://github.com/leon66666/DesignPattern] 一.设计模式 ...

  9. java 设计模式

    目录: 设计模式六大原则(1):单一职责原则 设计模式六大原则(2):里氏替换原则 设计模式六大原则(3):依赖倒置原则 设计模式六大原则(4):接口隔离原则 设计模式六大原则(5):迪米特法则 设计 ...

  10. 设计模式之单例模式(Singleton)

    设计模式之单例模式(Singleton) 设计模式是前辈的一些经验总结之后的精髓,学习设计模式可以针对不同的问题给出更加优雅的解答 单例模式可分为俩种:懒汉模式和饿汉模式.俩种模式分别有不同的优势和缺 ...

随机推荐

  1. python 面向对象进阶之元类metaclass

    一:知识储备 exec exec:三个参数 参数一:字符串形式的命令 参数二:全局作用域(字典形式),如果不指定,默认为globals() 参数三:局部作用域(字典形式),如果不指定,默认为local ...

  2. Python_doc文件写入SQLite数据库

    #docx文档题库包含很多段,每段一个题目,格式为:问题.(答案) #数据库datase.db中tiku表包含kechengmingcheng.zhanngji.timu.daan四个字段 impor ...

  3. Unity3D学习(二):使用JSON进行对象数据的存储读取

    前言 前段时间完成了自己的小游戏Konster的制作,今天重新又看了下代码.原先对关卡解锁数据的存储时用了Unity自带的PlayerPref(字典式存储数据). 读取关卡数据的代码: void Aw ...

  4. C/C++ 数据结构之算法

    数据结构中的排序算法. 排序算法的相关知识: (1)排序的概念:所谓排序就是要整理文件中的记录,使之按关键字递增(或递减)次序排列起来. (2)稳定的排序方法:在待排序的文件中,若存在多个关键字相同的 ...

  5. 用R语言进行文本挖掘和主题建模

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 我们每天都会遇到各种各样的文本数据,但大部分是非结构化的,并不是全部都是有价值的. 据估计,全球约80%的数据是非结构化的.这包括音频,视频 ...

  6. SSM-MyBatis-16:Mybatis中延迟加载

    ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 延迟加载: 所谓延迟加载是什么? 从字面意思理解到的是等一会再加载 从行为分析,他主要是缓解数据库压力,提高性 ...

  7. Spring Security4.1.3实现拦截登录后向登录页面跳转方式(redirect或forward)返回被拦截界面

    一.看下内部原理 简化后的认证过程分为7步: 用户访问网站,打开了一个链接(origin url). 请求发送给服务器,服务器判断用户请求了受保护的资源. 由于用户没有登录,服务器重定向到登录页面 填 ...

  8. web优化(二)

    上次说到js的阻塞dom渲染可能出现的白屏现象,所以对于js我们需要一些优化.首先我们可以模仿通信中的时分的概念,使用 setTime()来执行一段js代码然后渲染页面然后再执行一段js代码,这样可以 ...

  9. BITE

    <Google软件测试之道> 读后感言: p147 提到的BITE实在是太让人心动了, 一个简单的动作即可提交一个信息齐全的bug,连非专业测试人员也能轻松做到.身边很多人也都碰到过提交b ...

  10. ResultSet,RowSet,OracleCachedRowSet和RowSetMetaData区别及联系

    在java主要涉及到数据开发的过程中,我们会和数据库打交道很多,其中使用了数据集比如ResultSet和RowSet,经常使用两种,还有其它的一些,那么这两种的主要区别是什么呢?我们先来看它们引入的方 ...