我希望能够使用模式在运行时向现有类添加行为(通过其他方法/属性)。
这看起来与众所周知的装饰器模式非常相似,但是,我能够找到装饰器模式的示例不允许嵌套添加新方法。最好用一个例子说明这一点:
namespace Decorator {
// classes and types
// - component:
// - concrete component:
// - decorator:
// - concrete decorator:
class Program {
static void Main(string[] args) {
IServer serverA = new Server(); // has database services
IServer serverB = new Server(); // has web services
IServer serverC = new Server(); // has both database services and web services
// add behaviour using the decorator pattern
serverA = new DatabaseServerDecorator(serverA);
serverB = new WebServerDecorator(serverB);
serverC = new DatabaseServerDecorator(serverA);
serverC = new WebServerDecorator(serverA); // note the 2nd level which causes loss of 'awareness' of the DbDecorator
// test restart of servers
serverA.RestartServer();
serverB.RestartServer();
serverC.RestartServer();
// test restart of web services
var webServerB = serverB as WebServerDecorator;
var webServerC = serverB as WebServerDecorator;
webServerB.RestartWebServices();
webServerC.RestartWebServices();
// test restart of database services
var databaseServerA = serverA as DatabaseServerDecorator;
var databaseServerC = serverC as DatabaseServerDecorator; // this will not work (HOW TO FIX??)
databaseServerA.RestartDatabaseServices();
databaseServerC.RestartDatabaseServices();
Console.ReadKey();
}
}
// IComponent
public interface IServer {
void RestartServer();
}
// Component
public class Server : IServer {
public void RestartServer() {
Console.WriteLine("Server restarted.");
}
}
// DecoratorA
public class WebServerDecorator : IServer {
IServer _server;
public WebServerDecorator(IServer server) {
_server = server;
}
public void RestartServer() {
_server.RestartServer();
}
public void RestartWebServices() {
Console.WriteLine("Web services restarted.");
}
}
public class DatabaseServerDecorator : IServer {
IServer _server;
public DatabaseServerDecorator(IServer server) {
_server = server;
}
public void RestartServer() {
_server.RestartServer();
}
public void RestartDatabaseServices() {
Console.WriteLine("Database services restarted.");
}
}
}
(真正的代码将使用“if object is Type”进行识别,但为了简洁/清晰,已将其删除)
这可能吗?在上面的示例中,服务器可能具有多个“服务”,因此不希望必须创建每个可能的排列(随着服务数量的增长,这将变得难以管理)。
答案 0 :(得分:0)
对Console.WriteLine("database service ..")
的来电应属于RestartServer()
,因为它在逻辑上属于"接口合同"。这是Decorator模式的目标 - 你装饰界面提供的行为(但不多)。创建新方法(扩展接口契约)并不是Decorator的意图。不确定你想要实现什么,但也许你不应该过度抽象它?如何使用不同的界面,例如IWebServer
,IDatabaseServer
(实施IServer
)并装饰IWebServer
,IDatabaseServer
而不是IServer
?