2016-11-07 7 views
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 поставщиков имеют различные входные параметры так, что бы входные параметры процесса? Кроме того, я думаю, что не получаю многого, потому что у меня все еще есть параметр ftp FtpConnection ftp, что означает, что мне придется добавить DLL, которая имеет класс FtpConnection в каждом проекте, который будет использовать метод Connect.

Например, метод процесс поставщиков будет выглядеть следующим образом:

process(string fileName) //and it would download fileName 
process(string folderName) //create folder if it doesnt exist 

Есть ли шаблон дизайна можно использовать здесь, что бы чище и будет делать вещи проще?

+0

Вы можете просто переопределить метод «Процесс» (параметр как «Список») или я могу что-то пропустить? – hofmeister

+1

Подключиться/закрыть может быть фактически конструктор/распоряжаться (возможность заменить это с помощью инструкции '' using'] (https://msdn.microsoft.com/en-us/library/yh598w02.aspx), см. 'IDisposable '. Что касается разных методов, вы можете использовать generics для предоставления параметров в качестве класса настроек, например. 'using (var connection = new FTPConnection (...) {...}', экземпляр настроек может быть даже установлен как параметр конструктора, а затем доступен без необходимости его поставки для каждого вызова 'Process()' . – Sinatr

ответ

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

В конце концов в Поставщике

public class SupplierA:BaseSupplier 
    { 
     public override void DoSomething(SupplierSettingClass settings) 
     { 
       //Do specific stuff for your class. 
     } 
    } 
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); 

ИЛИ

using (MySupplier sup1 = new MySupplier()) 
{ 
    sup1.SomeProperty = "Hello"; 
    sup1.Process(creds); 
} 
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 is right, это шаблон метода шаблонов. В Gamma et al., Template Method описывается непосредственно после стратегии в главе «Поведенческие шаблоны».

+1

* Шаблон метод * узор – juunas

Смежные вопросы