.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) 设计模式是前辈的一些经验总结之后的精髓,学习设计模式可以针对不同的问题给出更加优雅的解答 单例模式可分为俩种:懒汉模式和饿汉模式.俩种模式分别有不同的优势和缺 ...
随机推荐
- git基础命令学习总结
git版本升级 git clone git://git.kernel.org/pub/scm/git/git.git 列出所有 Git 当时能找到的配置 git config --list git c ...
- goroutine和线程区别
从调度上看,goroutine的调度开销远远小于线程调度开销. OS的线程由OS内核调度,每隔几毫秒,一个硬件时钟中断发到CPU,CPU调用一个调度器内核函数.这个函数暂停当前正在运行的线程,把他的寄 ...
- Tiny4412中断介绍
通过几天裸板驱动开发,今天对ARM的中断做一些简单总结,前面我们已经了解了ARM的7种异常模式,中断是异常模式的一种,在ARM中异常事件发生将会触发中断,但是,所有的中断都不能直接访问cpu,而是都统 ...
- .NET面试常考算法
1.求质数 质数也成为素数,质数就是这个数除了1和他本身两个因数以外,没有其他因数的数,叫做质数,和他相反的是合数, 就是除了1和他本身两个因数以外,还友其他因数的数叫做合数. 1 nam ...
- c# xml操作(二)
c# xml操作(二) 此博文包含图片 (-- ::)转载▼ 标签: 杂谈 分类: c# 上次,我们介绍了增加和删除xml的一些操作,这次我们将介绍如何更改和读取xml特定节点.我们依然以上次的xml ...
- js中的拷贝问题
浅拷贝的实现 // 浅拷贝函数 var dad = {name:'chen',age:18}; var son = {sex:'男'}; function clone(dad,son){ var so ...
- 常用JS对象的方法总结
String 方法 描述 charAt() 返回在指定位置的字符. charCodeAt() 返回在指定的位置的字符的 Unicode 编码. concat() 连接字符串. indexOf() 检索 ...
- Javascript 进阶 面向对象编程 继承的一个例子
Javascript的难点就是面向对象编程,上一篇介绍了Javascript的两种继承方式:Javascript 进阶 继承,这篇使用一个例子来展示js如何面向对象编程,以及如何基于类实现继承. 1. ...
- Python中标准模块importlib详解
1 模块简介 Python提供了importlib包作为标准库的一部分.目的就是提供Python中import语句的实现(以及__import__函数).另外,importlib允许程序员创建他们自定 ...
- killall 、kill 、pkill 命令详解
killall 命令 Linux系统中的killall命令用于杀死指定名字的进程(kill processes by name).我们可以使用kill命令杀死指定进程PID的进程,如果要找到我们需要杀 ...