Предоставление данных объекта без нарушения инкапсуляции - PullRequest
3 голосов
/ 06 февраля 2012

Хороший объектно-ориентированный дизайн говорит о том, что объекты не должны раскрывать свои внутренности. Учитывая это, каков наилучший способ отображения данных?

Например, как бы вы отобразили поле данных после вызова DoSomethingToData в консольном приложении?

public class Foo {
    string data;

    public void DoSomethingToData(string someParam) {
        .....
    }
}

class Program {
    static void Main(string[] items) {
        var foo = new Foo();
        foo.DoSomethingToData("blah");
        ..... // how do we write data field to console without breaking encapsulation?
    }
}

Обновление: Я думал, что лучший способ сохранить инкапсуляцию - использовать шаблон наблюдателя (события), но никто не упомянул об этом. Это лучшее решение, чем показ свойства или результата метода?

Ответы [ 5 ]

5 голосов
/ 06 февраля 2012

Это зависит;

  • , если значение относится только к методу, сделать его возвращаемым значением метода
  • , если значение относится к объекту, выставить его черезсвойство

Я подозреваю, что это последнее, поэтому:

 public string Data { get { return data; } }

Это просто средство доступа - эквивалент getData() в Java, например.Это не раскрывает поле , но в конечном итоге ваш объект должен предоставить некоторый API для информации.Это не должно быть полным секретом.

3 голосов
/ 06 февраля 2012

Вы можете добавить метод ToString (или аналогичный), чтобы обеспечить строковое представление, подходящее для регистрации в консоли.

public class Foo
{
    private string data;

    public void DoSomethingToData(string someParam) {
        .....
    }

    public override string ToString()
    {
        return string.Format("Foo data: {0}", data);
    }
}

Это дает понять клиентам вашего класса, что содержимое данныхполе не предназначено для использования вне класса, за исключением отладки / ведения журнала.


В качестве альтернативы вы можете использовать частное свойство public getter, которое разрешает прямой (только для чтения) доступ к приватной строке, но обратите внимание, чтопредоставление такого свойства таким способом может привести к тому, что клиенты класса будут использовать поле Data для более общих целей, отличных от ведения журнала.

public string Data { get { return data; } }

Последний вариант заключается в использовании автоматически реализованныхсвойство и полностью удалите поле (автоматически реализованное свойство будет использовать свое собственное вспомогательное поле):

public string Data { get; private set; }
1 голос
/ 06 февраля 2012

Некоторые общие подходы:

  • Переопределение ToString () для некоторого общего текстового представления экземпляра (это может отражать ваши внутренние данные или нет, зависит от деталей и контекста)
  • Предоставление метода, если вычисление выполняется на основе определенных внутренних данных
  • Доступ к геттеру для неизменного раскрытия внутренних данных
  • Используйте отладчик и 'watch' для экземпляра класса, если вам нужно только проверить внутреннее поведение при отладке
0 голосов
/ 06 февраля 2012

Рассматривать данные как свойство.Данные - это свойство, которое не нужно хранить так, как оно было назначено.Свойство может быть получено / сохранено путем преобразования из / в его резервное хранилище.Более чем одно свойство может быть получено из комбинации преобразования внутренних ваших хранимых переменных.

private double booTheBackingStore;
private int myfactor;

public String data{
  get{
    return "<data>"+booTheBackingStore*booTheBackingStore+"</data>";
  }

  set{
    String boo = parselTheXml(value);
    double booger;
    Double.tryParse(boo, out booger);
    booTheBackingStore = Math.sqrt(booger);
  }
}


public double dada{
  get{
    return exoTransform(booTheBackingStore, myfactor);
  }
  set{
    booTheBackingStore = endoTransform(value, myfactor);
  }
}

Дополнительная информация:

Допустим, ваш класспросмотр веб-страницы, в котором есть режимы редактирования, просмотра, вставки, удаления.Для каждого из этих режимов ваш вид должен переустанавливать / переставлять виджеты.Более того, вам придется повторно применять стили.

С точки зрения MVP, вам необходимо отделить вашу презентацию от вашего взгляда.Представление должно выставить себя с точки зрения общественной собственности.Таким образом, свойство set / get mode будет инкапсулировать все внутренние свойства, которые необходимо выполнить в пользовательском интерфейсе.Ведущий не должен заботиться о том, как выглядит само представление.И у представления не должно быть никакой логики управления процессом или данными.

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

НадежныйПроектирование пользовательского интерфейса будет иметь конечный автомат на стороне сервера, который взаимодействует с конечным автоматом на стороне клиента, который, в свою очередь, упорядочивает агенты представления, что, в свою очередь, требует представления свойств UI-View.Ваш сервер не должен напрямую обращаться к клиенту.Также не должен ваш конечный автомат вашего клиента.Ваш докладчик направляется государством-клиентом для выполнения требований UI-View.Докладчик просто выдает спрос, скажем, на режим EDIT.Он не будет вмешиваться в UI-View, как реализован этот РЕДАКТИРОВАНИЕ.UI-View не должен поддерживать состояние UI.

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

Вам необходимо больше узнать о концепциях компонентного проектирования и "инкапсуляции".

0 голосов
/ 06 февраля 2012

Сделать недвижимость в классе Foo

    public string Data
    {
        get{return data;}
        set{data = value;}
    }
...