2013-03-22 4 views
1

Этот на самом деле очень простой. Может быть, кто-то приходит с хорошим :) решением.OO-шаблон для инъекции небольшого состояния

Имейте интерфейс, скажем, IComponent.

public interface IComponent { 
    string GetStatus(); 
} 

несколько реализаций IComponent нужно пропустить одну часть логики в GetStatus(), если текущее время между 12:00 утра и 12:10 утра. Но есть и другие реализации IComponent, которые не заботятся ни о каком временном интервале.

Так сказать:

public interface MyComponent : IComponent { 
    public string GetStatus() { 
     StringBuilder result = ...; 
     .... 
     if (/*current time between 12:00AM and 12:10AM */) 
      result.Append("good enough"); 
     else { 
      //calculate result 
      result.Append(/*calculated result*/); 
     } 
     ... 
     return result.ToString(); 
    } 
} 

Так что я в основном нужно это incapsulating

if (/*current time between 12:00AM and 12:10AM */) 
     return "good enough"; 

в некоторый класс, давайте назовем его 'SomeBehavior' или чего-л, и он может быть повторно использован в течение требуетсяIComponent -объекты.

Если это помогает, значение этого if - условие - «пропустить проверку файлов статистики», поэтому его можно назвать, например. SkipStatFilesCheckBehavior.

Хотя я не уверен в именовании, вот почему я здесь (вы можете назвать их как-то более подходящими, чем «поведение»). Каков наилучший способ его реализации? Как «поведение» может быть лучше введено в IComponent - реализации (например, через конструктор или что-то еще)? Будет ли решение расширяемым, если мне понадобится какое-то другое «поведение» в будущем? Возможно, в будущем некоторые виды «поведения» потребуют ссылки на IComponent-реализации.

+0

Вы можете переадресовать вызов GetStatus в какой-то делегат, который вы передаете в метод, который будет выполняться во время создания экземпляра в конструкторе. – Thomas

ответ

0

Я отправил ответ, используя Inheritance, но вы сказали в своем комментарии, что не хотите использовать наследование. Вот композиция пример:

public class Status 
{ 
    virtual public string getStatus() 
    { 
     StringBuilder result = new StringBuilder(); 
     if (1 == 1) //This IF statement will compare the time 
      result.Append("good enough"); 
     else 
     { 
      //calculate result 
      result.Append("calculated result"); 
     } 
     return result.ToString(); 
    } 
} 

public class Component1 : IComponent 
{ 
    public string getStatus() 
    { 
     Status component = new Status(); 
     String Status = component.getStatus(); 
     //Do the rest of the getStatus specific to Component1 
     return Status; 
    } 
} 

public class Component2 : IComponent 
{ 
    public string getStatus() 
    { 
     String Status = ""; 
     //Do the rest of the getStatus specific to Component2 
     return Status; 
    } 
} 
public interface IComponent 
{ 
    public string getStatus(); 
} 

В приведенном выше коде Component1 «имеет» статус, но компонент 2 не делает. Вы можете создать подкласс из класса Status, чтобы расширить поведение getStatus().

+0

Мне не нравится тот факт, что базовый класс содержит поведение, которое довольно неуместно (вообще) для некоторых из наследников. Как это можно продлить, если у меня есть несколько способов поведения? – Alec

0

Может быть что-то вроде этого:

interface Component { 
    String status(); 
} 
abstract class ComponentABC implements Component { 
    ComponentABC() { 
     this(false,false); 
    } 
    ComponentABC(boolean behaviour1,boolean behaviour2) { 
     this.behaviour1=behaviour1; 
     this.behaviour2=behaviour2; 
    } 
    public String status() { 
     String s="component"; 
     if(behaviour1) 
      s+=" with behaviour1"; 
     if(behaviour2) 
      s+=" with behaviour2"; 
     return s; 
    } 
    boolean behaviour1,behaviour2; 
} 
class BasicComponent extends ComponentABC {} 
class Behaviour1Component extends ComponentABC { 
    Behaviour1Component() { 
     super(true,false); 
    } 
} 
class Behaviour2Component extends ComponentABC { 
    Behaviour2Component() { 
     super(false,true); 
    } 
} 
class BehaviourBothComponent extends ComponentABC { 
    BehaviourBothComponent() { 
     super(true,true); 
    } 
} 
public class So15578113 { 
    public static void main(String[] args) { 
     Component[] components=new Component[]{new BasicComponent(),new Behaviour1Component(),new Behaviour2Component(),new BehaviourBothComponent()}; 
     for(Component component:components) 
      System.out.println(component.status()); 

    } 
} 
+0

На первый взгляд мне это нравится. Скорее всего, это будет принятый ответ. – Alec

+0

в java, я бы использовал перечисление для поведения, так как каждый может добавлять разные методы для каждого перечисления, и у вас есть перечисление для комбинаций поведения, но вы не можете сделать это в C#. –

0

Я хотел бы использовать шаблон прокси. Насколько я понимаю, в вашем случае, вы могли бы использовать его таким образом:

// common interface 
public class IComponent { 
    // I split getStatus, because both concrete cases have 
    // common pre and post processings 
    public string GetStatus() { 
     StringBuilder result = ...; 
     preProcess(result); 
     mainProcess(result); 
     postProcess(result); 
     return result.ToString(); 
    } 
    private void preProcess(StringBuilder str); 
    private void postProcess(StringBuilder str); 
    // proxied method 
    private void mainProcess(StringBuilder str); 
} 

// class implementing the basic behavior 
public class MyComponent : IComponent { 
    private void mainProcess(StringBuilder result) { 
     result.Append(/*calculated result*/); 
    } 
} 

// proxy class that calls the basic behavior under certain conditions only 
public class SkipStatFilesCheckBehavior : IComponent { 
    IComponent basicBehavior; 

    public SkipStatFilesCheckBehavior(IComponent newBasicBehavior) { 
     basicBehavior = newBasicBehavior; 
    } 

    private void mainProcess(StringBuilder result) { 
     if (/*current time between 12:00AM and 12:10AM */) 
      result.Append("good enough"); 
     else { 
      basicBehavior.mainProcess(result); 
     } 
    } 
} 
Смежные вопросы