标签:相关 完全 ring title 面向对象 abs opened bst 面向对象设计
面向对象编程追求的本质-提高扩展性、可维护性、灵活性和复用性。合理利用面向对象6个原则,能够很好的达到要求。如何利用好就是至关重要的了,前人总结了23+个设计模式能够让初学者更容易学到其中的精髓,本文就说说我对本人对装饰模式与代理模式的见解。
项目中要实现某个功能,前提条件是:1、该功能由许多单一功能的小功能组合而成;2、该功能中需要实现可灵活改变内部小功能的执行顺序;3、该功能内部的小功能不是固定的;4、用面向对象设计编程。
就比如装修房子:首先房子整体风格有多种,什么欧式风格,田园风格,地中海风格。每种风格中所用的家具种类和家具数量也不一样。要实现这个装修功能,咋个整啦?
有人会马上想到:继承,先建立两个抽象类(选择装修风格抽象和家具装修抽象)。具体风格类继承装修风格抽象类,具体家具类继承家具装修抽象类,客户端先选用具体风格,在更具具体风格去调用具体家具装饰。这样子看起来还不错,但是当风格和家具多了,而且每种风格的家具又是可变的,后期扩展又都会去更改抽象就很麻烦。
有处理这种特殊例子的好办法吗?有,那就是装饰者模式。在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
/// <summary> /// 房屋 /// </summary> public abstract class Home { /// <summary> /// 装修抽象 /// </summary> /// <returns></returns> public abstract string Decoration(); } /// <summary> /// 装饰抽象类,要让装饰完全取代抽象组件,所以必须继承自Home /// </summary> public abstract class Decorator:Home { private Home home; public Decorator(Home home) { this.home = home; } /// <summary> /// 装饰抽象 /// </summary> /// <returns></returns> public override string Decoration() { string result = string.Empty; if (home!=null) { result= home.Decoration(); } return result; } } /// <summary> /// 北欧风格 /// </summary> public class HomeOfEuropeanStyle:Home { /// <summary> /// 北欧风格装修 /// </summary> /// <returns></returns> public override string Decoration() { return "北欧风格装修(特有的操作)开始:\r\n1、相关的设计师设计出图纸;2、北欧风基础装修。\r\n"; } } /// <summary> /// 田园风 /// </summary> public class HomeOfCountrysideStyle:Home { /// <summary> /// 田园风装修 /// </summary> /// <returns></returns> public override string Decoration() { return "田园风格装修(特有的操作)开始:\r\n1、相关的设计师设计出图纸;2、田园风基础装修。\r\n"; } } /// <summary> /// 沙发 /// </summary> public class FurnitureOfSofa:Decorator { public FurnitureOfSofa(Home home) :base(home){} /// <summary> /// 具体装饰 /// </summary> /// <returns></returns> public override string Decoration() { string result = base.Decoration(); return result+ CutisVeraSofa(); } /// <summary> /// 安装真皮沙发 /// </summary> /// <returns></returns> private string CutisVeraSofa() { return "\r\n给装修的房子选择真皮沙发。"; } } /// <summary> /// 饭桌 /// </summary> public class FurnitureOfDinningTable : Decorator { public FurnitureOfDinningTable(Home home):base(home){ } /// <summary> /// 具体饭桌装饰 /// </summary> /// <returns></returns> public override string Decoration() { string result = base.Decoration(); return result + SolidWoodTablt(); } /// <summary> /// 安装实木餐桌 /// </summary> /// <returns></returns> private string SolidWoodTablt() { return "\r\n给装修的房子选择实木餐桌。"; } }
问题:为什么装饰者模式里面有继承,为什么又不用啦?
回答:这就是装饰者模式一大优点,这里抽象只做类型规范作用,不实现方法的复制。装饰者和被装饰者是同一个类型,这样被装饰者拥有了装饰者独有的功能。这样子我们可以在任何时候,给新的装饰者增加新的行为。如果是用继承,每当需要增加新的行为时,就要修改原程序的基类了。
优缺点:
使用场景:
毕业季到了,许多同学也将结束啃老族的生活,步入社会的大家庭自力更生-找工作。在以前,同学们就是频繁的进出各个人才招聘市场,每天都累成死狗一样,最后效果还不咋滴。近年来,招聘中介网步入人才市场,很好的解决了招聘单位和被招聘者费时费力却都不如意的问题。
在软件设计中,由于某些情况,客户端不想或不能直接访问一个对象,此时可以通过一个称为“代理”的角色来实现间接访问,该方案对应的设计模式被称为代理模式(给某一个对象提供一个代理或占位符,并由代理对象来控制对原对象的访问)。代理模式是一种应用很广泛的结构型设计模式,而且变化形式非常多,常见的代理形式包括远程代理、保护代理、虚拟代理、缓冲代理、职能引用代理等。
代理模式分类:
业务需求:系统中需要一个角色与各种游戏服务端交互的功能,在交互之前必须回去权限,在交互之后要统计交互信息。
/// <summary> /// 与游戏端交互抽象 /// </summary> public abstract class Interaction { /// <summary> /// 与游戏交互抽象方法 /// </summary> /// <param name="sLoginName">账号</param> /// <param name="AppId">游戏AppId</param> /// <returns></returns> public abstract string InteractionWithGame(string sLoginName,string AppId); } /// <summary> /// 真实的与游戏交互类 /// </summary> public class RealInteraction: Interaction { /// <summary> /// 与游戏交互 /// </summary> /// <param name="sLoginName"></param> /// <param name="AppId"></param> /// <returns></returns> public override string InteractionWithGame(string sLoginName, string AppId) { return sLoginName+$"正在与游戏:{AppId}交互..."; } } /// <summary> /// 与游戏交互代理 /// </summary> public class ProxyInteraction:Interaction { /// <summary> /// 真实的与游戏交互变量 /// </summary> private RealInteraction realInteraction=new RealInteraction(); /// <summary> /// 权限验证变量 /// </summary> private Validator validator; /// <summary> /// 统计功能比那辆 /// </summary> private Statistics statistics; /// <summary> /// 代理与游戏交互 /// </summary> /// <param name="sLoginName"></param> /// <param name="AppId"></param> /// <returns></returns> public override string InteractionWithGame(string sLoginName, string AppId) { //如果身份验证成功,则执行交互 if (this.Validate(sLoginName)) { //调用真实主题对象的交互方法 string result = realInteraction.InteractionWithGame(sLoginName, AppId); //交互统计 this.StatisticsInfo(sLoginName, AppId); return result; } else { return null; } } /// <summary> /// 创建访问验证对象并调用其Validate()方法实现身份验证获取权限 /// </summary> /// <param name="userId"></param> /// <returns></returns> private bool Validate(string userId) { validator = new Validator(); return validator.Validate(userId); } /// <summary> /// 交互统计 /// </summary> /// <param name="sLoginName"></param> /// <param name="AppId"></param> private void StatisticsInfo(string sLoginName, string AppId) { statistics = new Statistics(); statistics.InteractionStatistics(sLoginName, AppId); } } public class Validator { /// <summary> /// 判断是否有权限 /// </summary> /// <param name="sLoginName"></param> /// <returns></returns> public bool Validate(string sLoginName) { //在数据库中验证用户是否是合法 if (sLoginName.Equals("铁锅盖")) { return true; } else { return false; } } } public class Statistics { /// <summary> /// 交互统计 /// </summary> /// <param name="sLoginName"></param> /// <param name="AppId"></param> public string InteractionStatistics(string sLoginName, string AppId) { return "不同账号和不同游戏服务交互统计信息"; } } Client: /// <summary> /// 代理模式 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btn_proxy_Click(object sender, EventArgs e) { Interaction interaction = new ProxyInteraction(); txt_description.Text = interaction.InteractionWithGame("铁锅盖", "1001"); }
优缺点:
使用场景:
从UML类图可以看出来,装饰模式和代理模式在结构上很相似。都是真实类与代理/装饰继承同一个基类。那它们又有何差别啦?
使用代理模式,代理和真实对象之间的的关系通常在编译时就已经确定了,而装饰者能够在运行时动态的被构造。代理模式中,代理类对被代理的对象有控制权,决定其执行或者不执行。而装饰模式中,装饰类对代理对象没有控制权,只能为其增加一层装饰,以加强被装饰对象的功能。
标签:相关 完全 ring title 面向对象 abs opened bst 面向对象设计
原文地址:http://www.cnblogs.com/harveybarray/p/6821680.html