我们有一个应用程序可以联系多个不同的远程服务(SOAP,HTTPREQUEST)。然后我们执行不同的操作(导入,导出,更新,删除)。
今天我们有两个客户类和四个动作类。
问<!/强>
如何解耦这两个模块,以便我必须做最少的更改。 IE只添加一个新动作/新客户端。没什么。
客户端类
授权我们的客户端远程服务,它处理登录和退出。
行动类
持有url,方法来调用客户端。以及ExecuteActionMethod
用法
客户端类通过操作进行修饰,然后与客户端一起执行操作。
恐惧
我不希望:
- 每次添加新的客户端类时创建一个新的操作类 - 创建一个新的客户端类< / strong>每次我添加一个新的动作类
- 没有需要了解所有内容的上帝对象工厂
问题
这种方法的问题在于,当与不同的客户端交谈时,我需要不同的URL,在这种情况下需要不同的URL,与Soap服务交谈需要调用正确的方法。 行动本身就是这些信息的守护者。但是当我深入挖掘时,这肯定会发生变化。
情景1#
我最终创建了结合动作和结果的类。所以我有类似&#34; HttpImport&#34;(基于HttpClient和ImportAction)的类。这导致 X(客户端)* Y(操作),现在总计8个类,这真的很糟糕。
情景2#
一些代码的时间!在这种情况下,即使我使用抽象,实现也会将我的类绑定在一起。
问题在于每个操作都需要为每个客户端提供一个属性(请记住它们访问不同的端点)。因此,如果我要再添加一个客户端,我将不得不完成所有操作并为该客户端端点添加另一个属性,以及添加另一个deocrator来删除对正确端点的所有调用(请记住我现在每个动作都有三个属性)。如果我要创建另一个动作,它就是那个动作。所以N *次操作+ 1(操作),在这种情况下5更改。好一点但仍然没有。
场景3#
这是上帝对象工厂。这里我们摆脱了持有端点的属性,并通过构造函数提供了enpoint。这将导致创建各种客户端和操作的方法。与上面的 X(客户端)* Y(操作)相同,如果要添加某些内容,则会将累积到工厂内的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;
}
}
答案 0 :(得分:1)
访问者模式似乎适合此(Visitor)。 将操作视为访问者和客户端作为要访问的元素。将Action保持为抽象类而不是接口可能有助于提供样板代码。
BaseAction
。实施getHttpUrl()
,getHttpBody()
等下面的示例代码遵循Java语法。
public static void main() {
new HttpClient().performAction(new ImportAction());
}
public interface Client {
performAction(Action);
}
public class HttpClient implements Client {
public void accept(IAction a) {
a.visitHttp(this);
}
}
public abstract class Action {
public visitHttp(HttpClient c) {
getHttpUrl();
c.connect(getHttpUrl());
c.send(getHttpBody());
c.close;
}
public visitSoap(SoapClient c) {
}
public abstract String getHttpUrl();
public abstract String getHttpBody();
}
ImportAction extends Action {
@Override
getHttpUrl() {
}
@Override
getHttpBody() {
}
}