.net之设计模式
在上一篇文章里我通过具体场景总结了“.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之设计模式的更多相关文章
- MVVM设计模式和WPF中的实现(四)事件绑定
MVVM设计模式和在WPF中的实现(四) 事件绑定 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在WPF中 ...
- java EE设计模式简介
1.何为设计模式 设计模式提供了对常见应用设计问题的解决方案.在面向对象的编程中,设计模式通常在解决与对象创建和交互相关的问题,而非整体软件架构所面对的大规模问题,它们以样板代码的形式提供了通用的解决 ...
- 计算机程序的思维逻辑 (54) - 剖析Collections - 设计模式
上节我们提到,类Collections中大概有两类功能,第一类是对容器接口对象进行操作,第二类是返回一个容器接口对象,上节我们介绍了第一类,本节我们介绍第二类. 第二类方法大概可以分为两组: 接受其他 ...
- 《JavaScript设计模式 张》整理
最近在研读另外一本关于设计模式的书<JavaScript设计模式>,这本书中描述了更多的设计模式. 一.创建型设计模式 包括简单工厂.工厂方法.抽象工厂.建造者.原型和单例模式. 1)简单 ...
- 《JavaScript设计模式与开发实践》整理
最近在研读一本书<JavaScript设计模式与开发实践>,进阶用的. 一.高阶函数 高阶函数是指至少满足下列条件之一的函数. 1. 函数可以作为参数被传递. 2. 函数可以作为返回值输出 ...
- 设计模式之行为类模式大PK
行为类模式大PK 行为类模式包括责任链模式.命令模式.解释器模式.迭代器模式.中介者模式.备忘录模式.观察者模式.状态模式.策略 ...
- .NET设计模式访问者模式
一.访问者模式的定义: 表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作. 二.访问者模式的结构和角色: 1.Visitor 抽象访问者角色,为该 ...
- Java开发中的23种设计模式详解
[放弃了原文访问者模式的Demo,自己写了一个新使用场景的Demo,加上了自己的理解] [源码地址:https://github.com/leon66666/DesignPattern] 一.设计模式 ...
- java 设计模式
目录: 设计模式六大原则(1):单一职责原则 设计模式六大原则(2):里氏替换原则 设计模式六大原则(3):依赖倒置原则 设计模式六大原则(4):接口隔离原则 设计模式六大原则(5):迪米特法则 设计 ...
- 设计模式之单例模式(Singleton)
设计模式之单例模式(Singleton) 设计模式是前辈的一些经验总结之后的精髓,学习设计模式可以针对不同的问题给出更加优雅的解答 单例模式可分为俩种:懒汉模式和饿汉模式.俩种模式分别有不同的优势和缺 ...
随机推荐
- Spring Boot 快速入门笔记
Spirng boot笔记 简介 Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发 ...
- [CVPR 2017] Semantic Autoencoder for Zero-Shot Learning论文笔记
http://openaccess.thecvf.com/content_cvpr_2017/papers/Kodirov_Semantic_Autoencoder_for_CVPR_2017_pap ...
- 高通调试 SPI 屏的 bug
1. spi调试问题: 问题描述: spi屏幕lk启动的时候正常出现小企鹅,到kernel启动的过程黑屏并且花屏才到开机动画: 2. 黑屏的三个阶段: 参照:黑屏分析 分析开机过程黑屏,首先需要定位黑 ...
- 跨域cors方法(jsonp,document.domain,document.name)及iframe性质
这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据.只要协议.域名.端口有任何一个不同,都被 ...
- Exchanger兄弟线程间数据信息交换
一.简述 Exchanger可以在两个线程之间交换数据,只能是2个线程,他不支持更多的线程之间互换数据.当线程A调用Exchange对象的exchange()方法后,他会陷入阻塞状态,直到线程B也调用 ...
- PHP之连接mysql小练习
mysql Test.sql 1 -- phpMyAdmin SQL Dump -- version 4.6.6 -- https://www.phpmyadmin.net/ -- -- Host: ...
- SVN使用指引(Windows)
SVN使用指引(本地服务器为Windows) 原:http://wiki.open.qq.com/wiki/SVN%E4%BD%BF%E7%94%A8%E6%8C%87%E5%BC%95%EF%BC% ...
- 【手记】小心在where中使用NEWID()的大坑
这个表达式: --把GUID弄成正整数,然后取模 是随机返回0.1.2这三个数,不可能返回其它东西,但是如果把它用在where里面,就会发生很神奇的事情,比如这个查询: --创建一个只有1列3行的表, ...
- ECMAScript 6 入门 ----Generator 函数
本文转自:阮一峰老师的ECMAScript 6 入门,有时间可以看下评论! Generator 函数 简介 基本概念 Generator函数是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不 ...
- python教你用微信每天给女朋友说晚安
但凡一件事,稍微有些重复.我就考虑怎么样用程序来实现它. 这里给各位程序员朋友分享如何每天给朋友定时微信发送"晚安",故事,新闻,等等··· ···最好运行在服务器上,这样后台挂起 ...