在这种情况下应使用什么设计模式?

4
我有40个供应商需要进行FTP连接,执行一些操作后关闭连接。因此,这40个供应商都有自己的类,并且都具有FTP服务器的连接和断开连接功能,但它们都有不同的处理方法。
基本上,我有40个类都包含以下方法:
ftp.Connect();
//do something - this is different for all the classes
ftp.Close();

因此,“做某事”部分对于每个人都不同,它执行不同的任务,使用不同的变量等。

我的想法是:创建一个新类,将在所有40个供应商中实例化。这个类将有一个方法,看起来像这样:

public void Connect(FTPCredentials credentials, Process process)
{
    var ftp = new FtpConnection(credentials.Host, credentials.Username, credentials.Password);
    ftp.Open();
    ftp.Login();

    process(ftp);

    ftp.Close();
}

public delegate void Process(FtpConnection ftp/*, string name*/);

我这里的问题是40家供应商的所有方法都有不同的输入参数,那么Process的输入参数将会是什么?而且,我认为我并没有获得很多好处,因为我仍然在这里使用FtpConnection ftp参数,这意味着我必须在每个使用Connect方法的项目中添加具有FtpConnection类的dll。
例如,供应商中的process方法看起来像这样:
process(string fileName) //and it would download fileName
process(string folderName) //create folder if it doesnt exist

这里是否有一种设计模式可用,可以使代码更加简洁易懂,操作更加轻松?

你可以简单地重写 Process 方法(参数为 List),或者我可能漏掉了什么? - Andre Hofmeister
1
连接/关闭实际上可以是构造函数/释放(使用using语句替换的能力),请参阅IDisposable。至于不同的方法,您可以使用泛型来提供参数作为设置类,例如using (var connection = new FTPConnection<SettingsForFolder>(...) { ... },设置实例甚至可以设置为构造函数参数,然后在每个Process()调用时无需提供它即可访问。 - Sinatr
3个回答

1
我的印象是这样一个对象只被短暂地使用一次,且仅用于特定目的。因此,我会接受将特定参数存储在特定的派生类中。与mybirthname的解决方案类似,我会从一个抽象类开始,但定义方式不同:
public abstract class BaseSupplier
{
    protected BaseSupplier(FtpCredentials credentials)
    {
        _Credentials = credentials;
    }
    private FtpCredentials _Credentials;

    public void Run()
    {
        Connect();
        Process();
        Disconnect();
    }

    private void Connect() {/* your connection and login code */}
    private void Disconnect() {/* your disconnect code */}
    protected abstract void Process(); // to be filled in the derived class
}

public class ConcreteSupplier
{
    public ConcreteSupplier(FtpCredentials credentials, SomeType parameter) : base(credentials)
    { /* store extra parameters */ }

    override Process() {/*your concrete processing code */ }
}

如果我没记错的话,那被称为策略模式。
编辑: juunas是对的,它是模板方法模式。在Gamma等人的书中,在行为模式章节中直接描述了模板方法。

1
“模板方法”模式 - juunas

0
创建抽象类。
    public abstract class BaseSupplier
    {

        public void Connect(FTPCredentials credentials, Process process, SupplierSettingClass settings)
        {
             var ftp = new FtpConnection(credentials.Host, credentials.Username, credentials.Password);
             ftp.Open();
             ftp.Login();

             DoSomething(settings);

             ftp.Close();
        }

        public virtual void DoSomething(SupplierSettingClass settings)
        {
             //define base case;
        }
    }

你需要创建SupplierSettingClass,其中你将使用属性实现DoSomething方法的每个输入参数(文件夹名称、字段名称等)

    public class SupplierSettingClass
    {
        public string FolderName {get; set;}

        //and so on;
    }

最终在SupplierA中。
    public class SupplierA:BaseSupplier
    {
         public override void DoSomething(SupplierSettingClass settings)
         {
              //Do specific stuff for your class.
         }
    }

0

你可以使用一些巧妙的继承来将几乎所有所需的行为都包含在一个基本的抽象类中,就像这样:

public interface IProcessor
{
    void Process(Credentials credentials);
}

public class Credentials
{
    public string Host { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }
}

public abstract class SupplierBase : IProcessor, IDisposable
{
    protected FtpConnection _Connection;

    private void Connect(Credentials credentials)
    {
        //Create the ftp connection
        _Connection = new FtpConnection(credentials.Host, credentials.Username, credentials.Password);
        _Connection.Open();
        _Connection.Login();
    }

    private void Disconnect()
    {
        //Close and dispose the ftp connection
        _Connection.Close();
        _Connection.Dispose();
        _Connection = null;
    }

    public void Process(Credentials credentials)
    {
        Connect(credentials);
        Execute();
        Disconnect();
    }

    protected abstract void Execute();

    #region IDisposable

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            if (_Connection != null)
            {
                _Connection.Dispose();
                _Connection = null;
            }
        }
    }

    #endregion
}

public void MySupplier : SupplierBase
{
    //You can add unique supplier properties here.
    public string SomeProperty { get; set; }

    protected override void Execute()
    {
        //Implementation here
        Console.WriteLine(SomeProperty);
    }
}

以下是如何调用它的示例:

Credentials creds = new Credentials()
{
    Host = "127.0.0.1",
    Username = "test",
    Password = "test"
};

MySupplier sup1 = new MySupplier();
sup1.SomeProperty = "Hello";
sup1.Process(creds);

或者

using (MySupplier sup1 = new MySupplier())
{
    sup1.SomeProperty = "Hello";
    sup1.Process(creds);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接