首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java

为了开发有效的应用框架,你需要了解一些框架开发的通用技术。下面列出了一些有用的技术和方法,能够帮助你开发出既易用又可扩展的框架:

  • 通用点(Common spots)。
  • 扩展点(Hot spots)。
  • 黑盒框架(Black-box framework)。
  • 白盒框架(White-box framework)。
  • 灰盒框架(Gray-box framework)。
  • 设计模式(Design pattern)。

其中,通用点、扩展点和设计模式是用于开发框架的技术,黑盒、白盒和灰盒是开发框架的方法。

2.3.1  通用点

义如其名,通用点代表业务应用中反复出现的通用主题的位置。如果应用的某些部分重复出现,且其中又没有太多变化,那么我们就能将它从应用层中提取出来,作为通用点,封装成框架层的组件。通过把通用点移到框架层,避免了这些通用点在应用层的重复出现,从而促进了代码重用。这样,开发者能够简单地在他们的应用中引用框架中的通用点,从而减小了开发工作量。图2-3说明了通用点和框架以及业务应用的关系。

图2-3  通用点

在图2-3中,应用框架中包含了一些组件,这些组件实现了应用中一些不同的通用点。当开发者开始构建应用时,他们将引用框架组件实现的通用点,而不用亲自去开发它们。结果,他们要编写的代码总量就减少了。

什么样的主题有资格成为通用点呢?是不是必须在整个应用中,都以精确相同的方式出现的主题才有资格成为通用点呢?答案是否定的。只要差异不大,你依然可以把这个主题作为通用点;只是,需要通过参数化或配置设置项的方法,来处理这些小的变化。

将通用点主题移到框架组件中的实际工作并不困难,困难的是在分析阶段,如何从尚未开发的业务应用中识别出那些通用点。识别这些深藏在应用中的通用主题确实不易,通常要多次尝试才能做到。

通用点既可以存在于特定领域框架层中,也可以存在于跨领域框架层中。例如,商业文档交换(exchange of business documents)是B2B(business-to-business)应用的重要
 
主题,可以考虑把商业文档对象作为通用主题,放入特定领域框架层的组件中。另一个例子是数据加密服务。对很多类型的应用来说,数据的加密解密常常要被应用的不同部分使用,可以考虑把数据加密解密组件作为跨领域框架层组件,它简化了相关应用开发者的工作,减少了代码总量。

从技术观点来看,通用点的实现是直观易懂的。识别出通用点之后,框架设计者可以开发组件来封装通用点中的主题和逻辑;这些组件常常采用具体类或可执行(executable)的形式。为了包容组件中那些小的变化,可能需要为该组件引入一些配置数据。例如,你可以在配置文件中分配特定的段来参数化该框架组件。这样,若要在应用中引入该组件,开发者几乎不需要写代码就可以办到。

通用点捕捉应用中反复出现的主题。然而,每个业务应用都有其独特性;多个应用之间,既存在大量通用点,又会因每个应用的本质不同,而存在大量显著不同之处。因此,应用中可能有通用主题,也有显著的变化(variation)和客户化(customization)。为了保证在上述两种情况下,应用开发者都能利用框架,你作为框架设计者,也需要考虑这些变化的点。这把我们带到下一个主题:扩展点。

2.3.2  扩展点

扩展点是应用框架中具有灵活性的点。另一个看待扩展点的方法是,把它们看作嵌入框架的占位符(placeholder),将来在此处可以针对特定应用进行定制。

扩展点和通用点正好相反。在通用点中,通用主题在框架组件中得以具体实现;而在扩展点中,框架除安置了一个空的占位符之外什么也没有实现,这个占位符以后会被基于框架之上构建的业务应用填上客户化的实现。因为每个业务应用负责为框架中的扩展点提供它们自己的实现,所以框架在每个业务应用中的行为并不相同。这就是为什么尽管这些业务应用之间有显著差异,但框架还能够被设计成适应不同业务应用的原因。图2-4说明了应用框架如何通过扩展点具有了灵活性。

图2-4  扩展点

在图2-4中,应用框架层中的组件包含了扩展点,或者说供定制的空占位符。每个应用可能使用很多框架组件;当应用使用的框架组件包含扩展点的时候,该应用需要提供扩展点的实现。图中,代表扩展点的形状被涂上了不同的花色和阴影,以表示不同应用的不同实现。正如你所看到的,通过在扩展点内实现不同的逻辑,每个应用从框架组件获得了不同的行为。

和通用点类似,识别扩展点或许也不容易。为了识别潜在的扩展点,你必须彻底理解相关业务领域,理解业务应用的哪些点可能需要定制。如果框架内有太多不必要的扩展点,将导致应用开发团队额外的编码工作量;如果扩展点太少,框架的灵活性就差,使得应用开发团队期望的定制变得困难,于是他们的工作也变得更加困难。尽管通过覆盖(override)基类中大部分甚至全部虚方法(virtual method)来获得这种可定制性是有可能的,但这么做会降低代码的可重用性,并影响继承的效果。
 
在框架中创建扩展点并不像创建通用点那么直观易懂,其方法有二:继承法(inheritance approach)和组合法(composition approach)。先来看看继承法。

继承法(Inheritance Approach)

继承法依靠两个重要的面向对象概念:钩子方法(hook method)和模板方法(template method)。

钩子方法

钩子方法是一个占位符,供特定应用逻辑来填充。它是扩展点概念在实际类中的表现形式。在很多出版物里,术语“钩子方法”和“扩展点”可以互换。然而,虽然方法(method)是扩展点最普通的形式,但扩展点并不一定是一个方法,它也可能是一个类或应用程序。尽管钩子方法也可以出现在具体类中(这一点一会儿在本节就会看到),但通常它还是以抽象类中抽象方法的形式出现。

从定义来讲,抽象类是包含抽象方法的类。抽象类中的抽象方法不包含方法的实现;要使用该抽象类,必须从它继承一个类,并在该类中实现抽象类的抽象方法。由于上述特点,派生类(derived class)有机会引入客户化的逻辑,以使自己的行为符合特定业务需求的要求。下面的例子说明了抽象方法是如何工作的:

public abstract class BasicBusiness
{
     protected float income;
     //the template method
     public void ReportTax()
     {
          float sTax = CalculateStateTax();
          float fTax = CalculateFedTax();
          bool ok = CheckBankBalance(sTax + fTax);
          if (!ok)
          {
               FileBankruptcy();
          }
 
          else
          {
               SendMoneyToGov(sTax + fTax);
          }
     }

     protected abstract float CalculateStateTax();
     protected abstract float CalculateFedTax();
}

BasicBusiness类是一个抽象类,包含三个方法:ReportTax、CalculateStateTax和CalculateFedTax,其中后两个方法是抽象方法。BasicBusiness类用于向州和联邦政府报告所得税,它包含了虚构的税务申报的业务领域知识。如果账户余额足够,将给政府发一张支票;否则,账户持有人将申请破产。
ReportTax方法依靠两项信息来决定是缴税还是申报破产:缴纳给州政府的税款总额和缴纳给联邦政府的税款总额。税法规定了如何计算税款总额,例如,根据交易的地点和类型不同,将使用不同的税级。BasicBusiness组件的创建者并不知道税法信息。BasicBusiness类也不知道如何计算税款总额,而是把这个任务交给知道如何计算的类执行:两个抽象方法扮演了占位符的角色,它们以后会被填上计算税款总额的代码;正如你在上面例子中所看到的,CheckBankBalance方法使用这两个抽象方法的返回值作为参数,尽管这两个抽象方法还没有被实现。

当然,必须有代码真正实现CalculateStateTax和CalculateFedTax这两个抽象方法,否则ReportTax方法就不能提供有意义的功能。实际上,因为BasicBusiness类包含抽象方法,直接实例化它是不允许的,你需要创建一个派生(derive)自BasicBusiness的具体类,并实现它的两个抽象方法。下面的例子显示了一个类,它继承(extend)了BasicBusiness并实现了两个抽象方法:

public class NewYorkBusiness : BasicBusiness
{
     //implementation of abstract method
     protected override float CalculateStateTax()
 
     {
          return income * 0.1F;
     }
     //implementation of abstract method
     protected override float CalculateFedTax()
     {
          return income * 0.2F;
     }
}

NewYorkBusiness是一个具体类,它为纽约州提供了税款计算方法。有了NewYorkBusiness类中的客户化实现,BasicBusiness类中定义的ReportTax方法就能够执行有意义的行为了,如下例所示:
BasicBusiness nyBusiness = new NewYorkBusiness();
//ReportTax now will use the tax calculation algorithm defined for New York.
nyBusiness.ReportTax();

BasicBusiness caBusiness = new CaliforniaBusiness();
//ReportTax now will use the tax calculation algorithm defined for California.
caBusiness.ReportTax();

抽象方法对应用开发和框架开发都是非常重要的概念。假设BasicBusiness类是框架组件,而NewYorkBusiness类是应用组件,BasicBusiness类为应用留下了待填充的扩展点(CalculateStateTax和CalculateFedTax两个方法)。每个应用可以根据自己的特定需求,来填充这些扩展点。
尽管应用提供抽象方法的实现,但通常它并不直接调用抽象方法——抽象方法通常通过模板方法来调用。

模板方法

模板方法是GOF设计模式之一,它描述了特定操作序列的骨架(skeleton)或处理流程(process flow),而不是规定每个操作如何执行。在BasicBusiness组件的例子中,ReportTax就是一个模板方法,该方法描述了报税时涉及到哪些步骤,但没有描述每一步如何进行,因为它调用的有些方法还没有实现。模板方法强调的是不同对象及方法之间如何协作。在框架开发中,模板方法包含了业务领域知识,这些业务领域知识规定了不同方法应当如何协作;而抽象方法为模板方法调用的方法提供了客户化实现的手段。了解模板方法和钩子方法所包含的不同概念是很重要的;图2-5说明了框架中抽象方法(或钩子方法)与模板方法的关系。

图2-5 模板方法与抽象方法

图2-5中,左边是框架组件,其中有一个已经实现了的模板方法,模板方法中包含了特定业务领域的专门知识。左边的框架组件还有多个扩展点,它们以抽象方法的形式出现。图中从模板方法指向抽象方法的箭头,表示模板方法调用多个抽象方法,以实现特定应用的行为。

图2-5中,右边是应用组件,它继承了框架组件,并用特定应用的业务逻辑和知识实现了其中的抽象方法。因为应用组件继承了框架组件的功能,并覆盖了抽象方法(即钩子方法),所以,该覆盖的方法和框架组件中的模板方法共同协作,将业务领域知识和应用级业务逻辑结合在一起。

要支持扩展点,不仅可以通过上面讨论的钩子方法和模板方法,还可以通过组合法中的可插入对象(pluggable object)。

注释有多篇技术论文描述了这种框架方法,它们采用的术语是“好莱坞原则(Hollywood Principle)”,或“不要调用我,我会调用你原则(don’t call me, I’ll call you principle)”。该术语描述了这样一个特征:框架中的模板方法调用应用代码,而不是应用代码调用框架。它们引用这个术语是为了强调框架中的模板方法调用了在应用中实现的抽象方法,并控制其处理流程;然而,该术语稍微有些误导成分,因为大多数情况下,应用总是要调用框架的,尽管看上去是模板方法在调用应用代码,但其实是应用代码首先调用了模板方法。

组合法(Composition Approach)

继承法是支持框架扩展点的简单方法。但是,开发者要实现抽象方法,必须知道父类中有哪些可用的数据和方法,以及它们的相互关系,因此,开发者需要详细了解框架才能使用它。

例如,在NewYorkBusiness类中,实现CalculateStateTax和CalculateFedTax这两个方法,看上去很简单,但却要求开发者必须知道,有一个名为income的保护型浮点变量(protected float variable),且必须在调用任何一个CalculateXxxTax方法之前为该变量赋值。而且,父类向子类暴露其内部细节,降低了父类的封装度,这可能会导致开发者随意对类的内部状态做出超越其父类设计者意图的访问和修改。下面是一段用继承法实现扩展点的代码:

public class NewYorkBusiness : BasicBusiness
{
     protected override float CalculateStateTax()
     {
          return income * 0.1F;
        }
     protected override float CalculateFedTax()
     {
               return income * 0.2F;
        }
}

就像你所能想象到的一样,随着方法变得越来越复杂,开发者也许需要引用父类内更多的数据和方法,并且需要了解:通过设置这些数据的值和调用这些方法而改变对象的整个状态后,会有什么样的后果。

开发者必须了解父类细节信息这一要求,延长了框架的学习曲线,加重了使用框架的负担。为了让开发者不必知道框架组件的内部细节,有一个办法,那就是将扩展点定义为一组接口(interface),让这组接口和框架进行妥善的交互。开发者通过实现接口来创建组件,然后把该组件插入到框架中以定制它的行为。

可插入组件(Pluggable Component)

为了通过可插入组件来支持扩展点,应用框架必须首先为扩展点定义接口。接口描述了要与之兼容的类必须实现的一组方法。接口仅描述方法的外部特征,比如方法名、参数个数和参数类型,它并不描述方法如何实现。下面是用C#语言定义的一个接口的例子:

public interface ICalculateTax
{
     float CalculateStateTax();
     float CalculateFedTax();
     float Income
     {
         get;set;
         }
}

然后,你通过创建一个具体类并实现接口中定义的每个方法来支持ICalculateTax接口,就像下面显示的NewYorkBusiness类一样:

public class NewYorkBusiness : ICalculateTax
{
     private float income;
     public float Income
     {
          get { return income; }
 
          set { income = value; }
     }
     public float CalculateStateTax()
     {
          return income * 0.1F;
     }
     public float CalculateFedTax()
     {
          return income * 0.2F;
     }
}

NewYorkBusiness类实现了ICalculateTax接口,它现在已经兼容于,或者说可插入到框架中与ICalculateTax接口协作的扩展点了。借助接口的帮助,应用开发者可以通过把可插入应用组件加载到框架的扩展点,在框架中安排客户化的行为。图2-6说明了组合法如何支持应用框架扩展点。

图2-6  可插入应用组件

使用组合法支持扩展点,开发者需要创建可插入的应用组件,该组件的接口要和框架扩展点匹配。通过把应用组件和框架组件绑定在一起,开发者能够将组件插入到扩展点。
 
用组合法来支持扩展点,还要借助另一个称为策略模式(strategy)的GOF设计模式。在第5章,你将详细了解策略模式。

现在让我们修改一下纳税的例子,用组合法来支持扩展点。首先,我们需要修改BasicBusiness组件:我们这次不把它写成抽象类了,而是写成具体类。下面的代码片断显示了新的BasicBusiness组件:

public class BasicBusiness
{
     public void ReportTax (ICalculateTax calculator)
     {
          float sTax = calculator.CalculateStateTax();
          float fTax = calculator.CalculateFedTax();
          bool ok = CheckBankBalance(sTax + fTax);
          if (!ok)
          {
               FileBankruptcy();
          }
          else
          {
               SendMoneyToGov(sTax + fTax);
          }
     }
}

ReportTax方法现在有了一个ICalculateTax类型的输入参数,这个输入参数提供了客户化税款计算机制,它就是BasicBusiness框架组件中的扩展点。正如你知道的,通过插入客户化应用组件,我们就可以将特定应用的业务逻辑和知识“填充”到扩展点中去。
下面的例子显示了我们如何编写应用代码,来把应用组件插入到框架中去:

ICalculateTax nyBusiness = new NewYorkBusiness();
ICalculateTax caBusiness = new CaliforniaBusiness();

BasicBusiness basic= new BasicBusiness();
basic.ReportTax(nyBusiness);
basic.ReportTax(caBusiness);

在上面这个例子中,两个ReportTax方法将产生不同的结果,因为在两次调用中,框架组件绑定了不同的ICalculateTax组件。

为了让框架组件使用可插入对象,你要么使用上例中的(显式创建然后作为参数传递的)方法,要么把应用组件的类型信息(type information)保存到配置文件中,然后通过反射机制(reflection)创建适当组件,并动态插入到框架组件中。

识别通用点和扩展点,并实现它们,是应用框架开发的中心任务。根据你支持通用点和扩展点所采用的方式不同,你可以创建白盒框架、黑盒框架,或者灰盒框架。

2.3.3  白盒框架

白盒框架是由抽象类组成的框架。开发者使用白盒框架时,要继承框架中的抽象类来建立一个具体类。白盒框架使用继承法支持扩展点。图2-7显示了一个白盒框架。

图2-7  白盒框架

 
白盒框架相对容易开发。你可以先参考你以前开发过的类似应用,从中提取出抽象类,然后识别它们的扩展点,并把扩展点实现成抽象方法。开发白盒框架时,使用模板方法为每一个框架组件中处理流程的模式给出一个假设,这些假设常常建立在业务领域的专门知识和以前开发业务应用的经验之上。当开发者开始使用白盒框架时,它们只需在派生类中覆盖并实现为数不多的抽象方法,而不需担心整个处理流程以及抽象方法在框架内部如何被调用。这使得开发者可以把精力完全放在抽象方法上,而无须担心这些方法和框架的其他部分如何交互。

当然,几乎每件事都需权衡——白盒框架易于设计和实现,但它也有缺点。首先,它缺乏灵活性。当你通过模板方法决定框架组件中的处理流程时,实际上你是在组件中对处理流程和协调逻辑进行硬编码(hard-code)。虽然使用框架的开发者可以改变组件扩展点的逻辑,但整个处理流程已经固定了。当业务规则的改变引起组件中的处理流程需要改变的时候,这种被硬编码的处理流程就暴露出了其缺乏灵活性的缺点;由于处理流程和协调逻辑被固定了,你不得不更改已存在的组件,或者是写一个新的代替它。
白盒框架的另一个缺点是,它通常要求开发者了解很多框架组件的实现细节。当开发者实现框架组件中的抽象方法时,他经常需要在实现代码中引用抽象类的方法和变量,这就使了解框架组件的内部细节成了使用框架组件的先决条件。

黑盒框架通常采用组合法解决白盒框架遇到的难题,但是黑盒框架也有它的缺点。

2.3.4 黑盒框架

黑盒框架由直接可用的具体类组成。使用黑盒框架时,尽管开发者能够继承已存在的框架组件来达到客户化的目的,但更为通常的方法是,通过组合很多组件来达到预期目的。黑盒框架可能包含很多通用点,它借助组合法来支持扩展点。图2-8说明了一个黑盒框架。

图2-8  黑盒框架

由于黑盒框架使用了组合法,它提供了比白盒框架更大的灵活性,开发者能够任意挑选不同的组件来满足特定的应用需求。白盒框架通常要求开发者了解框架组件的实现细节;黑盒框架则不同,它由隐藏了内部实现的组件组成。使用这些组件只需通过定义明确的接口——比如特定的公共(public)方法和属性(property),开发者要使用框架,只需熟悉这些公共成员就行了。

和白盒框架相比,黑盒框架较难开发。把业务领域的专门知识封装到组件,满足很多应用场景的使用,并非易事:封装的东西太多,会导致组件难于在很多场景中使用;封装的东西太少,应用开发者就要开发大量组件并使协调逻辑更复杂。

黑盒框架优秀的灵活性不是免费的。当使用黑盒框架时,为了让众多组件协同工作,开发者必须实现他们自己的处理流程和协调逻辑;既然要控制那些组件如何协同工作,

 
所以在利用黑盒框架优秀灵活性的同时,开发者还承担了额外的工作量:为组件们“牵线”。相反,白盒框架在组件的模板方法中则是为你自动处理“牵线”问题。

使用黑盒框架的开发者,尽管没有使用白盒框架时要了解抽象类内部实现的问题,但是他们必须熟悉更多组件以及它们的使用,因为他们现在要处理更多的“活动件(moving part)”并把它们组装成需要的“机器”。

开发应用框架时,对框架是由抽象类还是具体类组成,并没有要求。实际上,纯粹的白盒框架和黑盒框架都是不切实际的。混合使用继承法和组合法,使你可以自由选择适合特定组件设计的最佳方法;这时,你实际上在创建灰盒框架。

2.3.5  灰盒框架

灰盒框架同时采用继承法和组合法,它通常既包含抽象类,又包含具体类。采用何种方法支持通用点和扩展点,要视具体组件而定。图2-9显示了一个灰盒框架。

注释因为包含虚方法的具体类,既能够被直接使用,也能够被另一个类继承,然后覆盖它的虚方法以改变它的行为;所以,只要这些具体类混合运用了继承法和组合法,灰盒框架只包含具体类是可能的。

实际中的应用框架最有可能是灰盒框架。特定的组件使用继承法还是组合法,要根据如下两个判断来决定:这个组件要实现什么功能?开发者在其业务应用中有可能怎样使用这个组件?

当我们选择继承法、组合法或是两者组合的时候,我们应当牢记权衡每种方法的性能、维护成本和易用性。

图2-9  灰盒框架

从性能角度讲,组合法往往比继承法慢,主要是因为要在运行时加载和访问额外的组件,才能达到预期的结果;当你组合使用多个组件的功能时,也增加了很多额外的调用开销。然而,使用继承法时,派生类本身通常就包含了大部分必须的功能,因而减少了程序需要创建和访问的对象的数量,并且消除了使用组合法时调用不同组件的额外代码。

维护成本是选择两种方法时要权衡的另一个方面。使用组合法时,开发者使用的是一组耦合度很低的框架组件,这使他们的应用更能适应变化,因而更加灵活和更易于扩展。然而,在应用部署(deploy)之后,负责后期支持的工程师必须面对许多额外的“活动件”,这将导致额外的维护工作量。例如,业务需求的一个改变可能导致框架组件的
 
改变:原因在于你使用的是组合法,也就是说,会有一系列的框架组件参与到一个特定的业务功能之中,所以在业务需求改变时,它们也很可能要跟着改变。且这些发生在多个组件中的改变,还增加了测试和部署的工作量。另一方面,如果使用继承法,比起组合法显得不够灵活,但是它引入的“活动件”较少。此时,因为业务功能由一个类层次(hierarchy of classes)提供,所以通常能够通过改变类层次树(hierarchical tree)中很少的类,就可以解决业务需求变化的问题。当然,应用框架的实际维护成本取决于框架的具体设计,以及业务需求变化的类型。但一般而言,要处理的“活动件”越少,维护成本就越低。

易用性也是设计应用框架时应考虑的一个方面。框架组件若采用继承法,通常能将复杂的协调逻辑和处理流程隐藏到父类或抽象类中,于是,开发者通常只需通过覆盖实现少数方法(method)就能够达到期望的结果。因此,只要不要求开发者去了解那些多得难于招架的父类细节,继承法的易用性还是很好的。组合法的易用性很大程度上依赖于开发者需要使用多少组件才能达到特定结果:使用一组松耦合的组件,常要求开发者了解它们,并亲自编写协调逻辑和处理流程来组织它们之间的协作,才能达到期望的结果。然而,如果你愿意牺牲灵活性,创建少数粗粒度的组件,以使开发者只需使用为数不多的组件就能达到目的,那么,框架就会变得更易用,开发也更有效率——因为这样做显著减少了开发者必须了解和编写的协调逻辑。

当你进行很多框架设计决定的时候,你必须牢记:没有银弹。你需要在不同的方法之间权衡——决定如何平衡它们,并创造出适合你的目的的应用框架,这就是你的工作。

2.3.6  设计模式

当你设计和开发应用框架时,你常常会碰到重复出现的设计难题,例如,如何提高处理流程改变的应对能力,如何改进特定应用的定制能力。设计模式描述了软件设计的共性问题的解决方案,有助于你解决开发应用框架中的一些共性问题。在Erich Gamma、Richard Helm、Ralph Johnson和John Vlissides——即“四人组(gang of four,GOF)”——的经典书籍《设计模式:可复用面向对象软件的基础》中,记录了许多普遍使用的设计模式,下面的列表描述了其中一部分设计模式及它们能解决的问题:

  • 策略模式(Strategy):处理应用中算法变化的设计。它支持开发者以“即插即用”的方式,定制特定应用的算法。
  • 桥接模式(Bridge):解耦(decouple)应用中抽象和实现的设计。它支持开发者为应用部件提供不同的实现,而不影响应用的其他部分。
  • 装饰模式(Decorator):提供处理数据的层次方法的设计。它支持开发者方便地装配处理数据的多个组件。
  • 观察者模式(Observer):提供订阅-分发通信模型的设计。它支持开发者方便地向多个对象分发信息。
  • 中介者模式(Mediator):阻止多个对象显式相互调用的设计。它支持开发者在不同对象之间建立松耦合(loosely coupled)的通信。
  • 模板方法模式(Template method):提供算法骨架的设计。它支持开发者在还没有定义算法如何实现的情况下,定义处理流程和协调逻辑。
  • 访问者模式(Visitor):定义新操作而不改变旧操作的设计。它支持开发者将一个操作与经常变化的协调逻辑解耦合。
  • 单件模式(Singleton):确保类只创建一个实例(instance)的设计。它支持开发者更好地控制对象的创建。
  • 抽象工厂模式(Abstract factory):提供创建对象族的接口而无须指定具体类的设计。它支持开发者减少应用中对具体类的引用,从而减少具体类发生变化时需要改变的代码量。

本书的其余部分,我们将看到,这些设计模式如何帮助我们开发应用框架,以及如何使用.NET平台实现它们。

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论