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

时间:2016-11-07 09:11:27

标签: c# design-patterns

我有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(string fileName) //and it would download fileName
process(string folderName) //create folder if it doesnt exist

我可以在这里使用的设计模式更干净,更容易吗?

3 个答案:

答案 0 :(得分: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 :(得分: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方法的每个输入参数实现为属性(folderName,fieldName等)

    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.
         }
    }

答案 2 :(得分:0)

您可以使用一些聪明的继承来包含一个基本abstract类中的所有必需行为,如下所示:

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);

OR

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