扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
表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
*/
】
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。