系统架构技能之设计模式—组合模式

  一、上篇回顾

      我们上篇主要讲述了结构型模式中的外观模式,外观模式作为结构型模式中的一个简单又实用的模式,外观模式通过封装细节来提供大粒度的调用,直接的好处就是,封装细节,提供了应用写程序的可维护性和易用性。外观模式一般应用在系统架构的服务层中,当我们是多个不同类型的客户端应用程序时,比如一个系统既可以在通过Web的形式访问,也可以通过客户端应用程序的形式时,可能通过外观模式来提供远程服务,让应用程序进行远程调用,这样通过外观形式提供服务,那么不管是什么样的客户端都访问一致的外观服务,那么以后就算是我们的应用服务发生变化,那么我们不需要修改没一个客户端应用的调用,只需要修改相应的外观应用即可。

  我们主要是讲述了以下的几种情况,使用外观模式可能更适合:

  1、我们在使用第三方类库或者API的时候,我们通过本地的API接口的封装,来完成对第三方API接口的粗粒度外观对象,通过这个外观对象可以很容易的完成服务的调用。

  2、我们在架构设计的过程中,一次的功能访问可能需要同时的调用很多个对象,那么如果我们在服务调用的时候,能够在应用程序调用中一次就能完成所有要同时调用的对象那该多好啊,外观模式无疑是最好的原则,特别是在分布式应用中,通过远程调用服务,通过外观模式降低应用程序与服务的交互次数,同时可以降低应用程序的复杂性。

  二、摘要

  本文将会讲述结构性模式中的另外一个常用的模式-组合模式,我们平时在面向对象的设计中,我想有一个原则经常被提及就是,我们在设计的时候,对象组合>类的继承,本篇将会将结合简单的实例来说明这方面的优势,并且完成对组合模式的主题思想的掌握。我们这样来简单的理解组合模式,组合模式就是把一些现有的对象或者元素,经过组合后组成新的对象,新的对象提供内部方法,可以让我们很方便的完成这些元素或者内部对象的访问和操作。我们也可以把组合对象理解成一个容器,容器提供各种访问其内部对象或者元素的API,我们只需要使用这些方法就可以操作它了。那么对象组合相比继承的优势有哪些呢?可能具体的优势,也不是一句二句就能表述清楚的,还是我们来看看图形的可视化的描述吧。

clip_image002  我们这里设计的是持久化服务写到一个基类中,然后继承自该基类的子类都会拥有内置的持久化方法,可能后续我们又要添加其他的针对某个具体的对象类,有一些个性化的服务,我们通过扩展这个类,进行继承,这样多重继承后,会有一个很大的问题。子类膨胀的问题,而且一般来说继承的重数达到5层左右的时候,性能上可能就会有一定的瓶颈。也不是好的设计的思路。这时候对象组合可能为我们提供了更好的解决方案。基于组合方式的话,可能我们可以这样来做,换个思路:就像我们的一个负责的对象,可以通过简单的对象来组成的道理差不多,其实。

clip_image004  通过上图,我们知道了,组合对象可以看作是一系列简单的对象组合成负责的对象的一个模式,复杂对象可以看作是简单对象的一个容器。这个复杂对象完成了简单对象的封装,通过这个容器完成对象内部简单对象的访问。

  三、本文大纲

       a、上篇回顾。

       b、摘要。

       c、本文大纲。

       d、组合模式的特点及使用场景。

       e、组合模式的经典实现。

       f、组合模式的其他方案。

       g、原型模式使用总结。

  四、组合模式的特点及使用场景

  组合模式是将一系列对象组合成树形结构用来表示整体和部分之间的关系,组合模式的主要目的是达到,访问组合对象和访问单个对象具有一致性。这里的组合对象比较特殊,本身他可以是由其他的对象组合而成,同时,这个组合对象又可以是组成更复杂对象的一个部分。我们来举个例子来说明吧,可能更直观。

clip_image006  这里我们可以理解为一个简单的查询组件可能有要满足上述的几类查询条件的输入类型,将这个组件作为一个容器,那么同事,这个容器又可以作为另外一个容器的组件来运行,那么我们又可以在分页控件中,将这个查询组件包含到其中。以为分页提供相应的查询元素的集成。

  我们一般在如下场景中使用组合模式比较方便:

  1、我们有的时候想用户使用一个复杂对象像使用简单对象一样的方式去访问,并且用户同意使用对象内部的所有的对象时,我们可以考虑使用该模式。这个怎么理解呢?我们使用复杂对象像使用简单对象一样的方式去访问的话,那么我们可以使用组合对象,我们把这些简单的对象进行组合,用组合对象进行包装,并且提供相应的操作组合对象内部的方法。结合上图中的例子,我们可以这样理解,我们把查询组件封装成一个用户控件,然后可以在其他的页面中进行调用。这个时候,我们可能考虑如何分部页面,如何能够动态的维护界面上的控件,是否显示,控件里面显示的文本和值是什么?等等,这些都是我们可以考虑的元素,那么我们如何来做呢?提供下面的几个方法。我还是给出图来说话吧:

clip_image008  包含上面的这些元素,那么我们可以通过一些相应的方法来进行访问内部的元素。我们给出简单的示例代码:

public QueryControl()
{
InitializeComponent();

this.InitControlList();
}

public event EventHandler handler;

private Dictionary<string,Control> _controlList = null;
/// <summary>
/// 初始化控件信息
/// </summary>
private void InitControlList()
{
this._controlList = new Dictionary<string,Control>();
}
/// <summary>
/// 返回界面控件中所有的查询条件控件列表
/// </summary>
/// <returns></returns>
public Dictionary<string,Control> GetControls()
{
return this._controlList;
}

/// <summary>
/// 添加查询控件到界面中
/// </summary>
/// <param name="control"></param>
/// <returns></returns>
public bool AddControl(string key,Control control)
{
if(this._controlList.ContainsKey(key))
return false;
this._controlList.Add(key,control);

return true;
}

/// <summary>
/// 移除指定键值的对象
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public bool RemoveControl(string key)
{
if (this._controlList.ContainsKey(key))
return false;
this._controlList.Remove(key);

return true;
}

public virtual void OnQuery()
{
if (this.handler != null)
handler(
this, new EventArgs());
}

public void Query(object sender, EventArgs e)
{
this.CreateSQL();
this.OnQuery();
}

/// <summary>
/// 根据选中的条件生成SQL语句
/// </summary>
private void CreateSQL()
{
throw new NotImplementedException();
}

it知识库系统架构技能之设计模式—组合模式,转载需保留来源!

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。