程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 用設計模式固化你的C#程序(3)

用設計模式固化你的C#程序(3)

編輯:C#入門知識

用設計模式固化你的C#程序(中篇)

Design Patterns: Solidify Your C# Application Architecture with Design Patterns中文版(中篇)
作者:Samir Bajaj
譯者:榮耀

【譯序:C#進階文章。譯者對Samir提供的C#例子進行了簡單整理(作者提供的某些代碼在譯者的環境中無法通過編譯),並編寫了對應的C++示例,一並置於譯注中,以便讀者比對。譯文中所有C#、C++程序調試環境均為Microsoft Visual Studio.NET 7.0 Beta2】

decorator

  客戶應用常常需要加強某些類的方法所提供的服務。可能需要分別在方法調用前後插入一些預先處理和後繼處理的代碼。要實現這個目標,一種辦法是干脆做成不同的方法調用。然而,這種方式不但麻煩,而且不利於框架的擴展。例如,如果對於不同的客戶來說明顯要執行不同的預先處理和後繼處理任務,應用程序邏輯將會因為條件語句而變得晦澀不清並難以維護。問題是如何才能增強類所提供的功能的同時又不影響客戶代碼,而Decorator模式正是所需。
讓我們來考察一個具有遠程文件傳輸功能的類的例子。這樣的類代碼可能如表5所示。

表5

class FileTransfer
{
public virtual void Download(string url, byte[] data, int size)
{
// 下載文件
}
public virtual void Upload(string url, byte[] data, int size)
{
// 上傳文件
}
}

  假定有一個客戶程序對這個功能感興趣。除了能夠上傳和下載文件外,客戶應用還希望能夠將所有的文件傳輸請求和執行訪問檢查寫入日志。基於decorator模式的一種實現方式是從FileTransfer類派生出一個類並重載虛方法,並於調用基類方法之前或之後,插入附加代碼。如表6所示。

表6

class Decorator : FileTransfer
{
private FileTransfer ft = new FileTransfer();
private bool IsAccessAllowed(string url)
{
bool result = true;
// 決定是否對請求的URL訪問授權
return result;
}
private void LogAccess(string url)
{
// 將URL、時間、用戶身份等信息寫入數據庫
Console.WriteLine("Logging access to {0}", url);
}
public override void Download(string url, byte[] data, int size)
{
if (!IsAccessAllowed(url))
return;
ft.Download(url, data, size);
LogAccess(url);
}
} 客戶程序可以繼續使用同樣的接口【譯注:並非C#語義的接口】進行工作。實際上,還可以進一步改進這個方案,可將FileTransfer類和Decorator類改為實現同一個具有Upload和Download方法的接口的類。如此,就可以使客戶程序只依照接口工作,而同具體實現徹底解耦。

  當一定范圍的擴展和任務可以在現有類的基礎上進行,並且將所有擴展都定義為類是不切實際的情況下,使用decorator模式可以動態、透明地添加或移去功能而不會影響客戶代碼。

【譯注:以下是decorator模式完整示例

C#示例:
using System;
class FileTransfer
{
public virtual void Download(string url, byte[] data, int size)
{
// 下載文件
}
public virtual void Upload(string url, byte[] data, int size)
{
// 上傳文件
}
}
class Decorator : FileTransfer
{
private FileTransfer ft = new FileTransfer();
private bool IsAccessAllowed(string url)
{
bool result = true;
// 決定是否對請求的URL訪問授權
return result;
}
private void LogAccess(string url)
{
// 將URL、時間、用戶身份等信息寫入數據庫
Console.WriteLine("Logging access to {0}", url);
}
public override void Download(string url, byte[] data, int size)
{
if (!IsAccessAllowed(url)) return;
ft.Download(url, data, size);
LogAccess(url);
}
public override void Upload(string url, byte[] data, int size)
{
if (!IsAccessAllowed(url)) return;
ft.Upload(url, data, size);
LogAccess(url);
}
}
class Application
{
public static void Main()
{
Console.Write("Enter URL to access: ");
string url = Console.ReadLine();
Console.Write("Enable logging and access check? ");
string input = Console.ReadLine();
char ch = char.Parse(input);
bool decoration = (ch == y || ch == Y);
FileTransfer ft = null;
if (!decoration)
ft = new FileTransfer();
else
ft = new Decorator();
byte[] buf = new byte[1024];
ft.Download(url, buf, 1024);
}
}
/*以下是某次運行時輸出結果:
Enter URL to access: www.csdn.net
Enable logging and access check? Y
Logging access to www.csdn.net
*/
C++示例:【譯注:下例中之所以混用std::string和byte數組只是為了便於和C#程序比對而已】
#include "stdafx.h";
#include
#include
using namespace std;
typedef unsigned char byte;
class FileTransfer
{
public:
virtual void Download(string url, byte data[], int size)
{
// 下載文件
}
virtual void Upload(string url, byte data[], int size)
{
// 上傳文件
}
};
class Decorator : public FileTransfer // decorated file transfer
{
private:
FileTransfer* ft;
bool IsAccessAllowed(string url)
{
bool result = true;
// 決定是否對請求的URL訪問授權
return result;
}
void LogAccess(string url)
{
// 將URL、時間、用戶身份等信息寫入數據庫
cout<<"Logging access to "< }
public:
Decorator()
{
ft = new FileTransfer();
}
~Decorator()
{
if (ft)
{
delete ft;
ft = NULL;
}
}
void Download(string url, byte data[], int size)
{
if (!IsAccessAllowed(url)) return;
ft->Download(url, data, size);
LogAccess(url);
}
void Upload(string url, byte data[], int size)
{
if (!IsAccessAllowed(url)) return;
ft->Upload(url, data, size);
LogAccess(url);
}
};
int _tmain(int argc, _TCHAR* argv[])
{
cout<<"Enter URL to access: ";
string url;
cin>>url;
cout<<"Enable logging and access check? Type y or Y to continue: ";
char ch;
cin>>ch;
bool decoration = (ch == y || ch == Y);
FileTransfer* ft = NULL;
if (!decoration)
ft = new FileTransfer();
else
ft = new Decorator();
byte* buf = new byte[1024];
ft->Download(url, buf, 1024);
delete []buf;
if (ft != NULL)
{
delete ft;
ft = NULL;
}
return 0;
}
/*以下是某次運行時輸出結果:
Enter URL to access: www.csdn.net
Enable logging and access check? Y
Logging access to www.csdn.net
*/


 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved