Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在这种情况下使用什么设计模式?_C#_Design Patterns - Fatal编程技术网

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

C# 在这种情况下使用什么设计模式?,c#,design-patterns,C#,Design Patterns,我有40家供应商需要建立ftp连接,在那里做些事情并关闭连接。因此,这40家供应商都有自己的类别,他们都有ftp服务器的连接和断开,但他们都有不同的处理方法 所以基本上我有40个使用这种方法的类: ftp.Connect(); //do something - this is different for all the classes ftp.Close(); 所以“做某事”部分对所有人来说都是不同的,它做不同的事情,使用不同的变量,等等 我想我要做的是:创建一个新类,它将在所有40个供应商中

我有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*/);
process(string fileName) //and it would download fileName
process(string folderName) //create folder if it doesnt exist
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);
    }
}
我这里的问题是,所有40家供应商的所有方法都有不同的输入参数,那么流程的输入参数是什么?另外,我认为我没有获得太多,因为我这里仍然有FtpConnection ftp参数,这意味着我必须在每个使用Connect方法的项目中添加具有FtpConnection类的dll

例如,供应商的流程方法如下所示:

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*/);
process(string fileName) //and it would download fileName
process(string folderName) //create folder if it doesnt exist
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);
    }
}
这里有没有一种设计模式可以更简洁、更简单?

创建抽象类

    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,在该类中,您将作为属性(folderName、fieldName等)实现DoSomething方法的每个输入参数

最后在供应商A

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

您可以使用一些巧妙的继承在一个基本
抽象
类中包含几乎所有必需的行为,如下所示:

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


我的印象是,这样一个物体只用于短期和单一的特定目的。因此,我将接受存储在特定派生类中的特定参数。与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等人中,模板方法直接在行为模式一章中的策略之后描述。

您可以简单地覆盖
过程
方法(参数为
列表
),或者我可能遗漏了什么?连接/关闭实际上可以是构造函数/处置(一种用语句替换的能力),请参见
IDisposable
。对于不同的方法,您可以使用泛型作为设置类提供参数,例如,
使用(var connection=new FTPConnection(…){…}
,甚至可以将设置实例设置为构造函数参数,然后访问,而无需为每个
进程()
调用提供它