.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) 设计模式是前辈的一些经验总结之后的精髓,学习设计模式可以针对不同的问题给出更加优雅的解答 单例模式可分为俩种:懒汉模式和饿汉模式.俩种模式分别有不同的优势和缺 ...
随机推荐
- 设置ActiveMQ的访问密码
1.设置ActiveMQ的访问密码,以提高ActiveMQ的安全性 2.在ActiveMQ的conf目录的activemq.xml中添加账号密码 2.1 添加的代码如下 <!-- 添加访问Ac ...
- 分布式系统之CAP理论杂记
分布式系统的CAP理论:理论首先把分布式系统中的三个特性进行了如下归纳:● 一致性(C):在分布式系统中的所有数据备份,在同一时刻是否同样的值.● 可用性(A):在集群中一部分节点故障后,集群整体是否 ...
- JavaScript的数据类型问题总结
一 JS中有哪些数据类型? -- 共 6 种数据类型,其中 5 种基本数据类型Undefined,Null,Boolean,Number和 String,1 种复杂数据类型Object.因为EC ...
- 当Ucenter和应用通信失败
http://blog.sina.com.cn/s/blog_775f158f010135uz.html 失败是常见的. 对于初次接触Ucenter的人来讲,添加一个自己的应用最头疼的就是发现通信失败 ...
- 远程连接MySQL(MariaDB)数据库
网络环境: MySQL(MariaDB)服务器的操作系统为 CentOS 7 MySQL(MariaDB)服务器IP:172.16.230.15 客户端操作系统为 Windows 2008 R2 客户 ...
- Python爬虫利器四之PhantomJS的用法
前言 大家有没有发现之前我们写的爬虫都有一个共性,就是只能爬取单纯的html代码,如果页面是JS渲染的该怎么办呢?如果我们单纯去分析一个个后台的请求,手动去摸索JS渲染的到的一些结果,那简直没天理了. ...
- Python cmp() 函数
描述 cmp(x,y) 函数用于比较2个对象,如果 x < y 返回 -1, 如果 x == y 返回 0, 如果 x > y 返回 1. 语法 以下是 cmp() 方法的语法:cmp( ...
- 用Java为Hyperledger Fabric(超级账本)开发区块链智能合约链代码之部署与运行示例代码
部署并运行 Java 链代码示例 您已经定义并启动了本地区块链网络,而且已构建 Java shim 客户端 JAR 并安装到本地 Maven 存储库中,现在已准备好在之前下载的 Hyperledger ...
- Java RESTful 框架的性能比较
来源:鸟窝, colobu.com/2015/11/17/Jax-RS-Performance-Comparison/ 如有好文章投稿,请点击 → 这里了解详情 在微服务流行的今天,我们会从纵向和横向 ...
- 【BZOJ 1002】: [FJOI2007]轮状病毒
题目大意:(略) 题解: 第一眼,这不是矩阵树裸体,看了看样例,心想3就有16,那100岂不是要上天…… 果然炸long long……emmmm该不会要打高精除吧……害怕,按照老师的话,不可能考高精除 ...