【发布时间】:2015-03-11 20:40:36
【问题描述】:
我们有一个应用程序可以联系几个不同的远程服务(SOAP、HTTPREQUEST)。然后我们执行不同的操作(导入、导出、更新、删除)。
今天我们有两个客户端类和四个操作类。
问题!
我怎样才能解耦这两个模块,以便我必须做最少的更改。 IE 只添加一个新动作/新客户端。仅此而已。
客户端类
针对远程服务授权我们的客户端,它处理登录和注销。
动作类
保存要针对客户端调用的 url,方法。以及 ExecuteActionMethod
用法
客户端类 get 装饰有一个动作,然后与客户端一起执行该动作。
恐惧
我不想:
- 每次添加新的客户端类时创建一个新的动作类
- 创建一个新的客户端类 每次我添加一个新的动作类
- 没有需要知道一切的上帝对象工厂
问题
这种方法的问题是,当与不同的客户端交谈时,我需要不同的信息,在这种情况下不同的 URL,与 Soap 服务交谈需要调用正确的方法。 操作本身就是这些信息的保存者。但随着我深入挖掘,这肯定会发生变化。
场景1#
我最终创建了结合了动作和结果的类。所以我有像“HttpImport”这样的类(基于 HttpClient 和 ImportAction)。这导致 X(Clients) * Y(Actions) 现在将 总共 8 个类,这真的很糟糕。
场景2#
是时候写一些代码了!在这种情况下,即使我使用抽象,实现也会将我的类绑定在一起。
这里的问题是每个动作都需要为每个客户端拥有一个属性(记住它们访问不同的端点)。因此,如果我要再添加一个 client 我将不得不执行所有操作并为该客户端端点添加另一个属性,以及添加另一个 deocrator 以将所有调用委托给正确的端点(记住我现在在每个动作中都有三个属性)。如果我要创建另一个动作,那就是那个动作。所以 N*次动作 + 1(动作),在这种情况下 5 变化。稍微好一点,但还没有。
场景3#
这是上帝对象工厂。在这里,我们摆脱了保存端点的属性,并通过构造函数提供了端点。这将产生用于创建各种客户端和操作的方法。同上X(Clients) * Y(Actions),如果要添加一些东西,这些会在工厂内部累积成8个新方法。工厂还必须保存端点信息。
代码
我的代码已经发展到 2:nd 场景。我不想建工厂,我在找你们。
有些事情告诉我,客户端类做了很多事情,应该以某种方式将它们与它们在内部实例化的类分离。
主要
static void Main(string[] args)
{
IAction iact = new ImportAction();
IDecorator idec = new HttpDecorator(iact);
IClient icli = new HttpClient(idec);
Console.Write(icli.connect().ToString());
Console.ReadKey();
}
IAction
public interface IAction
{
string[] Execute();
string HttpString { get; }
string SoapMethod { get; }
}
ImportAction
class ImportAction : IAction
{
private string soapmethod;
private string httpUrl;
public ImportAction()
{
this.HttpString = @"http://www.hereiswereactionsgo.com";
}
public string[] Execute()
{ //Execute the action!
return null;
}
public string HttpString { get; set; }
public string SoapMethod { get; set; }
}
IDecorator
public interface IDecorator
{
string GetActionString();
}
HttpDecorator
class HttpDecorator : IDecorator
{
private IAction _action;
public HttpDecorator(IAction action)
{
this._action = action;
}
public string GetActionString()
{
return _action.HttpString;
}
public string[] Execute()
{
throw new NotImplementedException();
}
}
IClient
public interface IClient
{
bool connect();
}
HttpClient
class HttpClient : IClient
{
private string _username;
private string _password;
private IDecorator _myaction;
private HttpWebRequest webReq;
public HttpClient(IDecorator action)
{
this._username = "myusername";
this._password = "mypassword";
this._myaction = action;
}
public bool connect()
{
bool result = false;
webReq = (HttpWebRequest)WebRequest.Create(_myaction.GetActionString());
webReq.Credentials = new NetworkCredential(_username, _password);
HttpWebResponse myHttpWebResponse = (HttpWebResponse)webReq.GetResponse();
if (myHttpWebResponse.StatusCode == HttpStatusCode.OK)
{
result = true;
}
return result;
}
}
【问题讨论】:
标签: c# design-patterns module decorator