Дизайн класса с интерфейсом - PullRequest
0 голосов
/ 19 января 2012

Обновлено

Как лучше всего настроить этот класс?т.е. вызывать метод SetupInstruction()?Я хочу сделать этот метод виртуальным, чтобы класс, который переопределял, мог иметь свою собственную реализацию.В переопределенном классе я буду устанавливать другие объекты / свойства.

public abstract class InstructionInfo : IInstruction
{
    protected readonly IUserSession UserSession;
    protected readonly IReadOnlySession ReadOnlySession;

    protected InstructionInfo(int instructionID)
    {
        InstructionID = instructionID;
    }

    protected virtual void SetupInstruction()
    {
        _myInstruction = null; //call db and set up...
    }

    #region interface members

    private Instruction _myInstruction;
    public Instruction MyInstruction
    {
        get
        {
            **SetupInstruction();**
            return _myInstruction;
        }
        private set { _myInstruction = value; }
    }

    #endregion
}

Ответы [ 5 ]

1 голос
/ 19 января 2012

Все зависит от того, как вы собираетесь использовать код.Если вы хотите, чтобы процесс установки был внутренним, вы можете вызвать этот метод из конструктора базового типа.Затем настройку можно настроить по производным типам путем переопределения метода.Точно так же, если вы хотите запустить некоторые общие задачи установки с шагом, где может произойти пользовательская настройка, вы можете создать установку, подобную этой:

protected InstructionInfo(...)
{
    // ...

    SetupInstruction();
}

private void SetupInstruction()
{
    // Common setup
    // ...

    // Custom setup
    SetupInstructionCore();
}

// Either an optionally overriddable method
protected virtual void SetupInstructionCore()
{
}

// Or a required override
protected abstract void SetupInstructionCore();
0 голосов
/ 19 января 2012

По большей части я бы просто спроектировал класс для настройки тех полей, которые ему нужны, в своем собственном конструкторе, и позволил производным классам устанавливать те, которые им нужны, только для них.

Если бы я хотел, чтобы определенное поле было переопределено, я бы использовал его через свойство с отложенной загрузкой.

public abstract class MyClass
{
  private SomeType _someField = null; // Never touch this field in any member but
                                      // the SomeProp property
                                      // Maybe use Lazy<SomeType> to make this more obvious.
  protected SomeType CreateSomeType();
  public SomeType SomeProp
  {
    get
    {
      return _someField = _someField ?? CreateSomeType();
    }
  }
}

Теперь я не думаю о "настройке«объект, я просто действую так, как будто у него всегда есть готовый к работе SomeProp, и пока я не использую его в конструкторе, он будет работать.

Если это не сработаетв конкретном случае я бы рассмотрел фабричный шаблон или шаблон репозитория.

0 голосов
/ 19 января 2012

Ваше InstructionInfo является юридическим лицом.Метод установки должен быть перемещен в класс репозитория, например.InstructionInfoRepository.GetInstructionInfoByID (), например.

Позже вы можете внедрить преобразованный InstructionInfoRepository (например, IInstructionInfoRepository) в другие компоненты, чтобы отделить логику доступа к базе данных и логику создания инструкции.Вы также можете добавить фиктивный IInstructionInfoRepository в те же компоненты во время модульного тестирования, чтобы избежать зависимостей от внешних ресурсов во время модульного тестирования.Во время интеграционного тестирования вы можете протестировать конкретную реализацию IInstructionInfoRepository.

0 голосов
/ 19 января 2012

Может быть, я что-то пропустил, но просто пример:

// a Base abstract class 
public abstract class MyAbs
{
    public MyAbs() {        
         Init();
    }

    public virtual void Init(){
         "Do base".Dump();
    }
}

//derived
public class Derived : MyAbs
{
    public override void Init(){
        "Do child".Dump();
    }
}

код для запуска, пример

Derived ab = new Derived();

Вывод?Основан на принципах ОО:

"Do child"

Надеюсь, что вы хотите.

0 голосов
/ 19 января 2012

Думаю, я не до конца понимаю ваш вопрос, но вам следует установить сеттер на MyInstruction protected, чтобы переопределяющий класс мог установить его на SetupInstruction().

Вы также должны дать собственнику более точное имя, например Instruction вместо MyInstruction.

...