2015-10-01 4 views
3

У меня есть два класса (A и B), который реализует тот же интерфейс (I) в C#. Интерфейс имеет 5 методов для реализации. Реализации двух из этих методов почти одинаковы как для A, так и для B, за исключением того, что каждая реализация использует другую переменную. Вот абстрактный макет моих классов.Лучший способ реализовать аналогичные методы двух разных классов?

class A : I 
{ 
    Folder folder; 
    void method() 
    { 
     //implementation uses ``folder`` 
    } 

class B : I 
{ 
    List list; 
    void method() 
    { 
     //implementation uses ``list`` 
    } 
} 

Поскольку реализация Method одинакова (за исключением одного параметра) Я хочу, чтобы реализовать Method только один раз. Каково наилучшее решение по шаблонам проектирования? одним простым вариантом является определение третьего класса, который реализует Method и принимает один параметр (либо list, либо folder), а затем называет его в пределах Method от A и B. Любое другое решение?

------------ Edit ---------------

Я не хочу, чтобы мои Method, чтобы получить какой-либо дополнительный параметр. В таких условиях не статический класс util лучше, чем определение абстрактного класса?

+3

Возможно, использовать абстрактный класс вместо интерфейса? –

ответ

3

Вы можете создать общий абстрактный базовый класс, который принимает общий параметр T и реализует I<T>. То же T будет передан Method, который будет реализован в базовом классе:

public interface I<T> 
{ 
    void Method(T t); 
} 

public abstract class Base<T> : I<T> 
{ 
      public Base(T t) 
      { 
        this.param = t; 
      } 

      private readonly T param; 
    public void Method() 
    { 
     // Do stuff 
    } 
} 

public class A : Base<Folder> 
{ 
      public A(Folder folder) : base(folder) 
      { } 
} 

public class B : Base<List> 
{ 
      public B(List list) : base(list) 
      { } 
} 

public class Folder { } 
public class List { } 

Теперь вы можете сделать:

static void Main() 
{ 
    var a = new A(new Folder()); 
    a.Method(); 

    var b = new B(new File()); 
    b.Method(); 
} 
+0

спасибо, однако я не хочу, чтобы мой '' method'' получал дополнительный параметр. –

+0

@ H.Z Я редактировал код. Вы можете взять параметр 'T' во время построения. –

+0

еще одна вещь, могу ли я также изменить некоторый признак моей логики реализации в базовом классе в зависимости от типа '' T'' (например, если (T является папкой)))? –

0

Одним из вариантов является использование абстрактного класса вместо интерфейса , Конечно, этот класс должен быть общим.

Второй вариант заключается в том, чтобы извлечь метод в класс «static utils», и оба используют этот «utils». Но это предполагает, что list и folder являются экземплярами одного и того же интерфейса.

На мой взгляд, первый вариант - лучший.

+0

Можете ли вы взглянуть на «Правку», которую я только что добавил в мой первоначальный пост? –

0

Если реализации метода отличаются только по типу переменной, используйте шаблон Template Method в сочетании с базовым базовым классом.

abstract class Base<T> : I 
{ 
    public void method() 
    { 
     var items = GetItems(); 
     HandleItems(items); 
    } 

    protected abstract IEnumerable<T> GetItems(); 

    void HandleItems(IEnumerable<T> items) 
    { 
     // do something with a sequence 
     foreach(var item in items) Console.WriteLine(item); 
    } 
} 

class A : Base<FolderItem> 
{ 
    Folder folder; 

    protected overrides IEnumerable<FolderItem> GetItems() {return folder.Items;} 

} 

class B : Base<ListItem> 
{ 
    List list; 

    protected overrides IEnumerable<ListItem> GetItems() {return list.Items;} 
} 
Смежные вопросы