欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
模板方法模式(Template Method Pattern)

一、 模板方法(Template Method)模式

準備一個(gè)抽象類(lèi),將部分邏輯以具體方法以及具體構造子的形式實(shí)現,然后聲明一些抽象方法來(lái)迫使子類(lèi)實(shí)現剩余的邏輯。不同的子類(lèi)可以以不同的方式實(shí)現這些抽象方法,從而對剩余的邏輯有不同的實(shí)現。這就是模版方法模式的用意。

很多人可能沒(méi)有想到,模版方法模式實(shí)際上是所有模式中最為常見(jiàn)的幾個(gè)模式之一,而且很多人可能使用過(guò)模版方法模式而沒(méi)有意識到自己已經(jīng)使用了這個(gè)模式。模版方法模式是基于繼承的代碼復用的基本技術(shù),模版方法模式的結構和用法也是面向對象設計的核心。

模版方法模式需要開(kāi)發(fā)抽象類(lèi)和具體子類(lèi)的設計師之間的協(xié)作。一個(gè)設計師負責給出一個(gè)算法的輪廓和骨架,另一些設計師則負責給出這個(gè)算法的各個(gè)邏輯步驟。代表這些具體邏輯步驟的方法稱(chēng)做基本方法(primitive method);而將這些基本法方法總匯起來(lái)的方法叫做模版方法(templatemethod),這個(gè)設計模式的名字就是從此而來(lái)。


二、 模版方法模式的結構

模版方法模式的靜態(tài)結構如下圖所示。

 

這里涉及到兩個(gè)角色:

  • 抽象模版(AbstractClass)角色有如下的責任:

定義了一個(gè)或多個(gè)抽象操作,以便讓子類(lèi)實(shí)現。這些抽象操作叫做基本操作,它們是一個(gè)頂級邏輯的組成步驟。

定義并實(shí)現了一個(gè)模版方法。這個(gè)模版方法一般是一個(gè)具體方法,它給出了一個(gè)頂級邏輯的骨架,而邏輯的組成步驟在相應的抽象操作中,推遲到子類(lèi)實(shí)現。頂級邏輯也有可能調用一些具體方法。

  • 具體模版(ConcreteClass)角色有如下的責任:

實(shí)現父類(lèi)所定義的一個(gè)或多個(gè)抽象方法,它們是一個(gè)頂級邏輯的組成步驟。

每一個(gè)抽象模版角色都可以有任意多個(gè)具體模版角色與之對應,而每一個(gè)具體模版角色都可以給出這些抽象方法(也就是頂級邏輯的組成步驟)的不同實(shí)現,從而使得頂級邏輯的實(shí)現各不相同。


三、 模板方法模式的示意性代碼

 

// Template Method pattern -- Structural example  
using System;

// "AbstractClass"
abstract class AbstractClass
{
  
// Methods
  abstract public void PrimitiveOperation1();
  
abstract public void PrimitiveOperation2();

  
// The Template method
  public void TemplateMethod()
  
{
    Console.WriteLine(
"In AbstractClass.TemplateMethod()");
    PrimitiveOperation1();
    PrimitiveOperation2();
  }

}


// "ConcreteClass"
class ConcreteClass : AbstractClass
{
  
// Methods
  public override void PrimitiveOperation1()
  
{
    Console.WriteLine(
"Called ConcreteClass.PrimitiveOperation1()");
  }


  
public override void PrimitiveOperation2()
  
{
    Console.WriteLine(
"Called ConcreteClass.PrimitiveOperation2()");
  }

}


/// 
/// Client test
/// 

public class Client
{
  
public static void Main( string[] args )
  
{
    
// Create instance and call template method
    ConcreteClass c = new ConcreteClass();
    c.TemplateMethod();
  }

}

 


四、 繼承作為復用的工具

使用繼承作為復用的手段必須慎重,C#語(yǔ)言的設計師對使用繼承作為復用的工具有著(zhù)不同層次上的認識。

不知其一

首先,初學(xué)C#的程序員可能不知道什么是繼承,或者認為"繼承"是高深的工具。那時(shí)候,大部分的功能復用都是通過(guò)委派進(jìn)行的。

知其一、不知其二

然后慢慢地,他們發(fā)現在C#語(yǔ)言里實(shí)現繼承并不困難,并且初步認識到繼承可以使子類(lèi)一下子得到基類(lèi)的行為。這時(shí)他們就會(huì )躍躍欲試了,試圖使用繼承作為功能復用的主要工具,并把原來(lái)應當使用委派的地方,改為使用繼承,這時(shí)繼承就有被濫用的危險。

知其二

很多面向對象的設計專(zhuān)家從1986年就開(kāi)始警告繼承關(guān)系被濫用的可能。有一些面向對象的編程語(yǔ)言,如SELF語(yǔ)言,甚至將類(lèi)的繼承關(guān)系從語(yǔ)言的功能中取消掉,改為完全使用委派。

其他的設計師雖然不提倡徹底取消繼承,但無(wú)一例外地鼓勵在設計中盡可能使甩委派關(guān)系代替繼承關(guān)系。比如在【GOF95】一書(shū)中,狀態(tài)模式、策略模式、裝飾模式、橋梁模式以及抽象工廠(chǎng)模式均是將依賴(lài)于繼承的實(shí)現轉換為基于對象的組合和聚合的實(shí)現,這些模式的要點(diǎn)就是使用委派關(guān)系代替繼承關(guān)系。

知其三

是不是繼承就根本不該使用呢?事實(shí)上對數據的抽象化、繼承、封裝和多態(tài)性并稱(chēng)C#和其他絕大多數的面向對象語(yǔ)言的幾項最重要的特性。繼承不應當被濫用,并不意味著(zhù)繼承根本就不該使用。因為繼承容易被濫用就徹底拋棄繼承,無(wú)異于因噎廢食。

繼承使得類(lèi)型的等級結構易于理解、維護和擴展,而類(lèi)型的等級結構非常適合于抽象化的設計、實(shí)現和復用。盡管【GOF95】所給出的設計模式基本上沒(méi)有太多基于繼承的模式,很多模式都是用繼承的辦法定義、實(shí)現接口的。多數的設計模式都描寫(xiě)一個(gè)以抽象類(lèi)作為基類(lèi),以具體類(lèi)作為實(shí)現的等級結構,比如適配器模式、合成模式、橋梁模式、狀態(tài)模式等。

模版方法模式則更進(jìn)了一步:此模式鼓勵恰當地使用繼承。此模式可以用來(lái)改寫(xiě)一些擁有相同功能的相關(guān)的類(lèi),將可復用的一般性的行為代碼移到基類(lèi)里面,而把特殊化的行為代碼移到子類(lèi)里面。

因此,熟悉模版方法模式便成為一個(gè)重新學(xué)習繼承的好地方。


五、 一個(gè)實(shí)際應用模板方法的例子

下面的例子演示了數據庫訪(fǎng)問(wèn)的模板方法。實(shí)際應用時(shí),請確保C盤(pán)根目錄下有nwind.mdb這個(gè)Access數據庫(可以從Office的安裝目錄下找到。中文版用戶(hù)的請注意字段名可能有所不同)。

 

// Template Method pattern -- Real World example  
using System;
using System.Data;
using System.Data.OleDb;

// "AbstractClass"
abstract class DataObject
{
  
// Methods
  abstract public void Connect();
  
abstract public void Select();
  
abstract public void Process();
  
abstract public void Disconnect();

  
// The "Template Method"
  public void Run()
  
{
    Connect();
    Select();
    Process();
    Disconnect();
  }

}


// "ConcreteClass"
class CustomerDataObject : DataObject
{
  
private string connectionString =
    
"provider=Microsoft.JET.OLEDB.4.0; "
    
+ "data source=c:\\nwind.mdb";
  
private string commandString;
  
private DataSet dataSet;
 
  
// Methods
  public override void Connect( )
  
{
    
// Nothing to do
  }


  
public override void Select( )
  
{
    commandString 
= "select CompanyName from Customers";
    OleDbDataAdapter dataAdapter 
= new OleDbDataAdapter(
      commandString, connectionString );
    dataSet 
= new DataSet();
    dataAdapter.Fill( dataSet, 
"Customers" );
  }


  
public override void Process()
  
{
    DataTable dataTable 
= dataSet.Tables["Customers"];
    
foreach( DataRow dataRow in dataTable.Rows )
      Console.WriteLine( dataRow[ 
"CompanyName" ] );
  }


  
public override void Disconnect()
  
{
    
// Nothing to do
  }

}


/// 
///  TemplateMethodApp test
/// 

public class TemplateMethodApp
{
  
public static void Main( string[] args )
  
{
    CustomerDataObject c 
= new CustomerDataObject( );
    c.Run();
  }

}

 

 

六、 模版方法模式中的方法

模版方法中的方法可以分為兩大類(lèi):模版方法(Template Method)和基本方法(Primitive Method)。

模版方法

一個(gè)模版方法是定義在抽象類(lèi)中的,把基本操作方法組合在一起形成一個(gè)總算法或一個(gè)總行為的方法。這個(gè)模版方法一般會(huì )在抽象類(lèi)中定義,并由子類(lèi)不加以修改地完全繼承下來(lái)。

基本方法

基本方法又可以分為三種:抽象方法(Abstract Method)、具體方法(Concrete Method)和鉤子方法(Hook Method)。

抽象方法:一個(gè)抽象方法由抽象類(lèi)聲明,由具體子類(lèi)實(shí)現。在C#語(yǔ)言里一個(gè)抽象方法以abstract關(guān)鍵字標示出來(lái)。

具體方法:一個(gè)具體方法由抽象類(lèi)聲明并實(shí)現,而子類(lèi)并不實(shí)現或置換。在C#語(yǔ)言里面,一個(gè)具體方法沒(méi)有abstract關(guān)鍵字。

鉤子方法:一個(gè)鉤子方法由抽象類(lèi)聲明并實(shí)現,而子類(lèi)會(huì )加以擴展。通常抽象類(lèi)給出的實(shí)現是一個(gè)空實(shí)現,作為方法的默認實(shí)現。(VisualFoxPro中項目向導建立的項目會(huì )使用一個(gè)AppHook類(lèi)實(shí)現監視項目成員變化,調整系統結構的工作。)鉤子方法的名字通常以do開(kāi)始。


七、 重構的原則

在對一個(gè)繼承的等級結構做重構時(shí),一個(gè)應當遵從的原則便是將行為盡量移動(dòng)到結構的高端,而將狀態(tài)盡量移動(dòng)到結構的低端。

1995年,Auer曾在文獻【AUER95】中指出:

  1. 應當根據行為而不是狀態(tài)定義一個(gè)類(lèi)。也就是說(shuō),一個(gè)類(lèi)的實(shí)現首先建立在行為的基礎之上,而不是建立在狀態(tài)的基礎之上。
  2. 在實(shí)現行為時(shí),是用抽象狀態(tài)而不是用具體狀態(tài)。如果一個(gè)行為涉及到對象的狀態(tài)時(shí),使用間接的引用而不是直接的引用。換言之,應當使用取值方法而不是直接引用屬性。
  3. 給操作劃分層次。一個(gè)類(lèi)的行為應當放到一個(gè)小組核心方法(Kernel Methods)里面,這些方法可以很方便地在子類(lèi)中加以置換。
  4.  將狀態(tài)屬性的確認推遲到子類(lèi)中。不要在抽象類(lèi)中過(guò)早地聲明屬性變量,應將它們盡量地推遲到子類(lèi)中去聲明。在抽象超類(lèi)中,如果需要狀態(tài)屬性的話(huà),可以調用抽象的取值方法,而將抽象的取值方法的實(shí)現放到具體子類(lèi)中。

如果能夠遵從這樣的原則,那么就可以在等級結構中將接口與實(shí)現分隔開(kāi)來(lái),將抽象與具體分割開(kāi)來(lái),從而保證代碼可以最大限度地被復用。這個(gè)過(guò)程實(shí)際上是將設計師引導到模版方法模式上去。

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
設計模式之九(模版方法模式)
.NET設計模式(16):模版方法(Template Method)
圖解Java設計模式之模板模式
Template method pattern 模板方法模式
模板方法模式——每日的生活行為
《Head First設計模式》閱讀筆記.第八章
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久