您的位置:首页 > 其它

对设计模式的总结之装饰模式与代理模式

2017-05-09 13:53 253 查看

前言

面向对象编程追求的本质-提高扩展性、可维护性、灵活性和复用性。合理利用面向对象6个原则,能够很好的达到要求。如何利用好就是至关重要的了,前人总结了23+个设计模式能够让初学者更容易学到其中的精髓,本文就说说我对本人对装饰模式与代理模式的见解。

设计模式链接

对设计模式的总结之原则

对设计模式的总结之简单工厂与策略模式

对设计模式的总结之装饰模式与代理模式

对设计模式的总结之工厂方法模式和抽象工厂模式

装饰模式与代理模式

装饰模式

项目中要实现某个功能,前提条件是:1、该功能由许多单一功能的小功能组合而成;2、该功能中需要实现可灵活改变内部小功能的执行顺序;3、该功能内部的小功能不是固定的;4、用面向对象设计编程。

就比如装修房子:首先房子整体风格有多种,什么欧式风格,田园风格,地中海风格。每种风格中所用的家具种类和家具数量也不一样。要实现这个装修功能,咋个整啦?

有人会马上想到:继承,先建立两个抽象类(选择装修风格抽象和家具装修抽象)。具体风格类继承装修风格抽象类,具体家具类继承家具装修抽象类,客户端先选用具体风格,在更具具体风格去调用具体家具装饰。这样子看起来还不错,但是当风格和家具多了,而且每种风格的家具又是可变的,后期扩展又都会去更改抽象就很麻烦。

有处理这种特殊例子的好办法吗?有,那就是装饰者模式。在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。

/// <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");
}


View Code

总结

优缺点:

客户通过代理调用功能,降低了耦合性。

更改代理,可以搭配出许多功能,增加了代码灵活性和可扩展性。

远程代理可以将功能分散到其他服务端,提高系统效率;缓存代理可使高频率访问对象访问速率更快;保护代理可以控制访问权限。

在使用者和被使用者中间加了代理,在一定程度上降低了处理速率。

使用场景:

当客户端对象需要访问远程主机中的对象时可以使用远程代理。

当需要用一个消耗资源较少的对象来代表一个消耗资源较多的对象,从而降低系统开销、缩短运行时间时可以使用虚拟代理,例如一个对象需要很长时间才能完成加载时。

当需要为某一个被频繁访问的操作结果提供一个临时存储空间,以供多个客户端共享访问这些结果时可以使用缓冲代理。

当需要控制对一个对象的访问,为不同用户提供不同级别的访问权限时可以使用保护代理。

当需要为一个对象的访问(引用)提供一些额外的操作时可以使用智能引用代理。

装饰模式与代理模式区别

从UML类图可以看出来,装饰模式和代理模式在结构上很相似。都是真实类与代理/装饰继承同一个基类。那它们又有何差别啦?

使用代理模式,代理和真实对象之间的的关系通常在编译时就已经确定了,而装饰者能够在运行时动态的被构造。代理模式中,代理类对被代理的对象有控制权,决定其执行或者不执行。而装饰模式中,装饰类对代理对象没有控制权,只能为其增加一层装饰,以加强被装饰对象的功能。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: