文档章节

常用的设计模式和代码

白志华
 白志华
发布于 2015/10/18 10:55
字数 2582
阅读 10
收藏 0

设计模式是软件开发讨论中,亘古不变的话题,今天又拿出来说道两句,也是对设计模式的一个复习吧。


工厂方法模式

       工厂方法模型定义了一个用于创建对象的接口,让子类决定实例化哪一个类,工厂模式使一个类的实例化延迟到了其子类中。工厂方法模式是优化的简单工厂模式,它很好的支持了“开闭原则”。每一个具体的工厂只能构建一个类的对象。具体工厂类与产品类是一对一的关系。

/// <summary>  
/// 抽象产品类
/// </summary>  
public class Product{
	public Product(){
		Console.Write("new Product");
	} 
}

/// <summary>  
/// 具体产品类A
/// </summary>
public class ConcreteProductA:Product {
	public ConcreteProduct(){
		Console.Write("创建了一个 ConcreteProductA");
	}
}

/// <summary>  
/// 具体产品类B
/// </summary>
public class ConcreteProductB:Product {
	public ConcreteProduct(){
		Console.Write("创建了一个 ConcreteProductB");
	}
}

/// <summary>  
/// 抽象的创建者
/// </summary>
abstract public class Creator{
	
	//抽象的工厂方法
	public abstract Product FactoryMethod();
	
}

/// <summary>  
/// 具体方法工厂A
/// </summary>
public class ConcreteCreatorA:Creator{
	//返回一个产品A的对象
	public override Product FactoryMethod(){
		return new ConcreteProductA();
	}
}

/// <summary>  
/// 具体方法工厂B
/// </summary>
public class ConcreteCreatorB:Creator{
	//返回一个产品B的对象
	public override Product FactoryMethod(){
		return new ConcreteProductB();
	}
}

//client端
static void Main(string[] args)  
{  
    Creator c = new ConcreteCreatorA();
    Product p = c.FcatoryMethod();
    
    c = new ConcreteCreatorB();
    p = c.FcatoryMethod();
    
    Console.ReadLine();
}


适配器模式Adapter

      适配器模式是将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

      两个成熟的类需要通信,但是接口不同,由于开闭原则,我们不能去修改这两个类的接口,所以就需要一个适配器来完成衔接过程。

      变压器就是很好的适配器模式的例子。用电设备所需要的电压是9V,但是电线上的电压却是220V的,我们不能去更改它们的电压输入或输出,所以我们用到了变压器。变压器是220V的输入,9V的输出。这样就可以将200V的电压变为9V的电压,用变压器将用电设备连接到了电线上工作了。

       上面两幅图中,都是Client端需要Request这个方法,但是Adaptee没有这个方法,所以就需要提供一个中间件/包装类(Wrapper)Adapter类来衔接。不同的是第一幅图Adapter继承自Adaptee,而第二幅图是在Adapter类中包装了一个Adaptee的实例。这就决定了第一幅图讲的是“类的结构模式”,而第二幅图则是“对象的结构模式”。

/// <summary>  
/// 目标接口,客户所期待的接口。
/// </summary> 
public class Target{
	public virtual void Request(){
		Console.Write("我是本系统中的普通请求.");
	}
	
}

/// <summary>  
/// 适配器,匹配2个接口不一致的类
/// </summary> 
public class Adapter:Target{
	private Adaptee adaptee = new Adaptee();
	public void Request(){
		adaptee.SpecificRequest();
	}
}

/// <summary>  
/// 源接口,与客户期待的接口不一致
/// </summary> 
public class Adaptee(){
	public void SpecificRequest(){
		Console.Write("我是原有的真实调用的系统");
	}
}

//client端
static void Main(string[] args)  
{  
	Target t = new Adapter();
	t.Request();
	
	Console.ReadLine();
}

桥接模式 Bridge

      桥接模式将抽象部分与它的实现部分分离,使它们都可以独立地变化。它很好的支持了开闭原则和组合及复用原则。实现系统可能有多角度分类,每一种分类都有可能变化,那么就把这些多角度分离出来让他们独立变化,减少他们之间的耦合。

      2个相互耦合的系列,每个系列都有各自的产品变动。将这2个系列抽象成2个角色类,将各自的变化封装到对象的角色类中,然后再将2个角色类之间用组合的关系表示,这样就大大简化了使用类继承的复杂性,逻辑变得清晰了,易于扩展和维护。

      桥接模式封装了变化,完成了解耦,实现了弱耦合

/// <summary>  
/// 抽象部分
/// </summary> 
public class Abstraction{
	protected Implementor implementor;
	
	public void SetImplementor(Implementor implementor){
		this.implementor = implementor;
	}
	
	public virtual void Operation(){
		implementor.OperationImp();
	}
}

/// <summary>  
/// 被提炼的抽象部分
/// </summary> 
public class RefinedAbstraction:Abstraction{
	
	public override void Operation(){
		implementor.OperationImp();
	}
}

/// <summary>  
/// 实现部分
/// </summary> 
abstract public class Implementor{
	public abstract void OperationImp();
}

/// <summary>  
/// 具体实现A
/// </summary> 
public class conscreteImplementorA:Implementor{
	pulic override void OperationImp(){
		Console.Write("我是具体的A");
	}
}

/// <summary>  
/// 具体实现B
/// </summary> 
public class conscreteImplementorB:Implementor{
	pulic override void OperationImp(){
		Console.Write("我是具体的B");
	}
}
//client端
static void Main(string[] args)  
{  
	Abstraction ab = new RefinedAbstraction();
	ab.SetImplementor(new conscreteImplementorA());
	ab.Operaton();
	
	ab.SetImplementor(new conscreteImplementorB());
	ab.Operaton();
	
	Console.ReadLine();
}

具体的实例可以看我的另一篇博文《面与卤的鹊桥相会——桥接模式

装饰模式 Decorator

       装饰模式动态地给一个对象添加一些额外的职责,就增加功能来说,它比生成子类更灵活。也可以这样说,装饰模式把复杂类中的核心职责和装饰功能区分开了,这样既简化了复杂类,有去除了相关类中重复的装饰逻辑。装饰模式没有通过继承原有类来扩展功能,但却达到了一样的目的,而且比继承更加灵活,所以可以说装饰模式是继承关系的一种替代方案。装饰模式解耦了核心和装饰功能,所以也是强调了松耦合 

/// <summary>  
/// 最高接口,被装饰者和“装饰品”都继承于此
/// </summary> 
abstract public class Component{
	public abstract void Operation();
}

/// <summary>  
/// 具体的被装饰者
/// </summary> 
public class Concretecomponent:Component{
	public override void Operation(){
		Console.Write("具体对象的装饰操作");
	}
}

/// <summary>  
/// 装饰类
/// </summary> 
abstract public class Decorator:Component(){
	protected Component component;
	
	public void SetComponent(Component component){
		this.component = component;
	}
	public override void Operation(){
		if(component!=null) component.Operation();
	}
}

/// <summary>  
/// 具体的装饰类A
/// </summary> 
public class ConcreteDecoratorA:Decorator{
	private string addedState;
	public override void Operation(){
		base.Operation();
		addedState="New State";
		Console.Write("具体装饰A的操作(添加了新的状态)");
	}
}

/// <summary>  
/// 具体的装饰类B
/// </summary> 
public class ConcreteDecoratorB:Decorator{
	public override void Operartion(){
		base.Operation();
		AddedBehavior();
		Console.WriteLine("具体装饰B的操作(添加了新的方法)");
	}
	private void AddedBehavior(){
		//添加新的行为
	}
}

//client端
static void Main(string[] args)  
{  
	Concretecomponent c = new Concretecomponent();
	Decorator d1 = new ConcreteDecoratorA();
	Decorator d2 = new ConcreteDecoratorB();
	
	d1.SetComponent(c);
	d2.SetComponent(d1);//注意这里装饰的是d1,因为这里的d1是装饰了d1的c。
	d2.Operation();
	
	Console.ReadLine();
}

外观模式 Facade

       外观模式为子系统中的一组接口提供了一个一致的界面,此模式定义了一个高层接口,这个接口使得这些子系统更加容易使用。

       外观模式中,客户对各个具体的子系统是不了解的,所以对这些子系统进行了封装,对外只提供了用户所明白的单一而简单的接口,用户直接使用这个接口就可以完成操作,而不用去理睬具体的过程,而且子系统的变化不会影响到用户,这样就做到了信息隐蔽。

       这就相当于新生接待员。新生对入学流程不清楚,但是接待员学长可是明白的。学生跟着接待员就可以把各个手续办理完毕了。可以说外观模式封装了细节

 

/// <summary>  
/// 高层的统一接口,封装了子系统繁杂的接口。
/// </summary> 
public class Facade{
	private SubSystemOne one;
	private SubSystemTwo two;
	private SubSystemThree three;
	
	public Facade(){
		one = new SubSystemOne();
		two = new SubSystemTwo();
		three = new SubSystemThree();
	}
	
	public void MethodA(){
		one.MethodOne();
		two.MethodTwo();
	}
	
	public void MethodB(){
		one.MethodOne();
		three.MethodThree();
	}
	
}

/// <summary>  
/// 子系统One。
/// </summary> 
public class SubSystemOne{
	public void MethodOne(){
		Console.Write("我是One");
	}
}

/// <summary>  
/// 子系统Two
/// </summary> 
public class SubSystemTwo{
	public void MethodTwo(){
		Console.Write("我是Two");
	}
}

/// <summary>  
/// 子系统Three
/// </summary> 
public class SubSystemThree{
	public void MethodThree(){
		Console.Write("我是Three");
	}
}

//client端
static void Main(string[] args)  
{
	Facade f1 = new Facade();
	f1.MethodA();
	
	Facade f2 = new Facade();
	f2.MethodB();
	
	Console.ReadLine();
}

策略模式 Strategy

       策略模式定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。本模式使得算法的变化不会影响到使用算法的客户。

       策略模式将每一个算法封装到一个具有公共接口的独立类中,解除了客户与具体算法的直接耦合,是客户改变算法更为容易。

        策略模式+简单工厂+反射+配置文件可以组成更为灵活的方式。 


/// <summary>  
/// 算法的公共接口
/// </summary> 
abstract public class Strategy{
	public abstract void AlgorithmInterface();
}

/// <summary>  
/// 具体算法A
/// </summary> 
public class ConcreteStrategyA:Strategy{
	public override void AlgorithmInterface(){
		Console.Write("具体算法A");
	}
}

/// <summary>  
/// 具体算法B
/// </summary> 
public class ConcreteStrategyB:Strategy{
	public override void AlgorithmInterface(){
		Console.Write("具体算法B");
	}
}

/// <summary>  
/// 具体算法C
/// </summary> 
public class ConcreteStrategyC:Strategy{
	public override void AlgorithmInterface(){
		Console.Write("具体算法C");
	}
}

/// <summary>  
/// 上下文,用来维护一个对Strategy对象的引用。
/// </summary> 
public class Context{
	private Strategy strategy;
	
	public Context(Strategy strategy){
		this.strategy=strategy;
	}
	
	//上下文接口
	public void ContextInterface(){
		strategy.AlgorithmInterface();
	}
}

//client端
static void Main(string[] args)
{
	Context context = new Context(new ConcreteStrategyA());
	context.ContextInterface();
	
	context = new Context(new ConcreteStrategyB());
	context.ContextInterface();
	
	context = new Context(new ConcreteStrategyC());
	context.ContextInterface();
	
	Console.ReadLine();
}

观察者模式 Observer

       观察者模式定义了对象间的一种一对多的依赖关系,当一个对象的状态发生变化时,所有依赖它的对象都会得到通知,并被自动更新,

         系统中有两个方面,其中一个方面依赖与另一个方面,我们把这两个方面抽象,是各自可以独立的变化和复用。

         就像我们现在所用到的分层,不就是一层层的依赖么?还有系统组件升级,系统功能也跟着变化,这也属于观察者模式。

/// <summary>  
/// 抽象观察类
/// </summary> 
abstract public class Observer{
	public abstract void Update();
}

/// <summary>  
/// 具体观察类
/// </summary> 
public class Concreteobserver:Observer{
	private string name;
	private string observerState;
	private ConcreteSubject subject;
	
	public Concreteobserver(ConcreteSubject subject,string name){
		this.subject=subject;
		this.name= name;
	}
	
	public override void Update(){
		observerState=subject.GetState();
		Console.write("观察者{0}的新状态是{1}",name,observerState);
	}
}

/// <summary>  
/// 抽象主题类
/// </summary> 
abstract public class Subject(){
	private List<observer> observers = new List<observer>() ;
	
	public void  Attach(Observer observer){
		observers.Add(Observer);
	}
	
	public void Detach(Observer Observer){
		observers.Remove(Observer);
	}
	
	public void NotifyObservers(){
		foreach(Observer o in observers){
			o.Update();
		}
	}
}

/// <summary>  
/// 具体主题类
/// </summary> 
public class ConcreteSubject:Subject{
	private string subjectState;
	
	public string SubjectState{
		get{return subjectstate;}
		set{subjectstrate=value;}
	}
	
	public void GetState(){
		return subjectstate;
	}
}

//client端
static void Main(string[] args)  
{  
	ConcreteSubject c = new ConcreteSubject();
	Concreteobserver o1 = new Concreteobserver(c,"X");
	Concreteobserver o2 = new Concreteobserver(c,"Y");
	Concreteobserver o3 = new Concreteobserver((c,"Z");
	c.Attach(o1);
	c.Attach(o2);
	c.Attach(o3);
	c.subjectstate="abc";
	c.Nofify();
	
	Console.ReadLine();
}


欲了解其他模式,请查看我的这3篇博文:

设计模式之创建型模式

设计模式之结构型模式

设计模式之行为型模式

版权声明:本文为博主原创文章,未经博主允许不得转载。

本文转载自:http://blog.csdn.net/xiaoxian8023/article/details/8115240

白志华
粉丝 34
博文 265
码字总数 57524
作品 0
长沙
程序员
私信 提问
六个前端开发工程师必备的Web设计模式/模块资源

Yahoo的设计模式库 Yahoo的设计模式库包含了很多可以帮助开发设计人员解决遇到的问题的资源,包括开发中常常需要处理的导航,互动效果及其布局网格等大家常用的组件和模块 响应式设计模式库 ...

gbin1
2014/07/30
14
0
JavaScript 中常见设计模式-代理模式

     代理模式   情景:小明追女生 A   非代理模式:小明 =花=> 女生A   代理模式:小明 =花=> 让女生A的好友B帮忙 =花=> 女生A   代理模式的特点   代理对象和本体对象具有一...

webstack前端栈
2018/06/15
0
0
JavaScript 的一些设计模式

设计模式的定义:在面向对象软件设计过程中针对特定问题的简洁而优雅的解决方案 设计模式是前人解决某个特定场景下对而总结出来的一些解决方案。可能刚开始接触编程还没有什么经验的时候,会...

格西南
2019/08/20
0
0
从工厂模式说起,简单聊聊设计模式在前端中的应用

设计模式是一套可以被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式,是为了可重用代码,让代码更容易被他人理解并且提高代码的可靠性。 设计模式的基本原则...

罗辑思维前端开发团队
2019/07/26
0
0
JavaScript 常见设计模式

前言 设计模式,这一话题一直都是程序员谈论的"高端"话题之一。许多程序员从设计模式中学到了设计软件的灵感和解决方案。 有人认为设计模式只在 C++或者 Java 中有用武之地,JavaScript 这种...

YeeWang王大白
2019/03/08
0
0

没有更多内容

加载失败,请刷新页面

加载更多

测试定时

23/58

FalconChen
昨天
43
0
新海软件邮政市场监管综合信息平台

二、系统功能 该平台包括邮政普遍服务管理、快递管理两大系统,涵盖了地图定位、普服信息、快递信息、GIS管理、网格管理、视频监控、数据分析(BI)、系统设置等八大模块,全面反映了区域邮政...

neocean
昨天
165
0
【微记忆】用户隐私政策与条款

微记忆尊重并保护所有注册用户的个人隐私权。为了给您提供更准确、更贴心的服务,微记忆会按照本隐私权政策的规定储存并使用您的个人信息。微记忆承诺将以高度严格的审慎义务对待这些信息。除...

微记忆
昨天
69
0
两周自制脚本语言-第7天 添加函数功能

第7天 添加函数功能 基本的函数定义与调用执行、引入闭包使Stone语言可以将变量赋值为函数,或将函数作为参数传递给其他函数 有些函数将有返回值的归为函数,没有返回值的归为子程序 7.1 扩充...

果汁分你一半
昨天
105
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部