Шаблон памяти и нарушение инкапсуляции - PullRequest
0 голосов
/ 25 марта 2020

Через inte rnet Я сталкиваюсь с примерами реализации шаблона memento , которые я считаю совершенно неверными. Они могут быть записаны как Java и C#.

Вот несколько из них

  1. Неправильная реализация шаблона Memento 1
  2. Некорректная реализация шаблона Memento 2
  3. Некорректная реализация шаблона Memento 3

Код:

public class Originator
{
    private string _state; //the private field of originator that shouldn't be exposed!!!!

    public Memento CreateMemento()
    {
        return new Memento(_state);
    }

    public void SetMemento(Memento memento)
    {
        _state = memento.GetState();
    }
}


public class Memento
{
    private string _state;

    public Memento(string state)
    {
        _state = state;
    }

    public string GetState()
    {
        return _state;  // here caretaker can access to private field of originator!!!
    }
}


public class Caretaker
{
    public Memento Memento { get; set; }
}

В коде я оставил комментарии, которые должны описывать ситуацию.

Класс смотрителя может читать приватное поле инициатора через память, которая нарушает один из основных принципов паттерна сувенира:

Инкапсуляция объекта не должна нарушаться.

Итак, вопрос в том, прав ли я?

Ответы [ 3 ]

1 голос
/ 26 марта 2020

Итак, вопрос в том, прав ли я?

Да, вы правы: все примеры являются неправильными реализациями шаблона проектирования Memento, потому что класс Memento предоставляет свои внутренние зависимость через метод publi c. Как вы заметили, это позволяет Caretaker (или любому другому классу) получать личную информацию о Originator.

Предыдущие ответы фокусируются на состоянии внутреннего поля и на том, может ли состояние Memento варьируются независимо от Originator. Инкапсуляция нарушается в большей степени, чем путем выставления состояния: она нарушается путем раскрытия зависимостей. Метод получения publi c раскрывает тот факт, что Originator зависит от String. Это конфиденциальная информация, которая не должна быть раскрыта.

I wi sh Я мог бы сказать, что дезинформация необычна в отношении шаблонов проектирования; но вы найдете неточные и вводящие в заблуждение статьи о шаблонах проектирования в Inte rnet, в том числе здесь, в SO и Wikipedia .

Единственный источник со 100% гарантированной точностью - это оригинальный GoF книга. Онлайн-ресурсы всегда должны быть сверены с книгой. Что касается паттерна Memento, мне нравится статья https://refactoring.guru/design-patterns/memento.

0 голосов
/ 25 марта 2020

Если мы добавим логи c для проверки эволюции переменных, вы заметите, как Originator и Memento не совместно используют одни и те же данные.

public class Originator
{
    private string _state = "originator_initial_state";

    public Memento CreateMemento()
    {
        return new Memento(_state);
    }

    public void DoSomeLogic()
    {
        _state = _state + " modified";
    }

    public void SetMemento(Memento memento)
    {
        _state = memento.GetState();
    }
}

public class Memento
{
    private string _state;

    public Memento(string state)
    {
        _state = state;
    }

    public string GetState()
    {
        return _state;
    }
}

Теперь давайте поработаем с ними:

Originator myOriginator = new Originator();
Memento memento1 = myOriginator.CreateMemento();

myOriginator.DoSomeLogic();

Memento memento2 = myOriginator.CreateMemento();

string memento1_state = memento1.GetState();
string memento2_state = memento2.GetState();

Console.WriteLine(memento1_state);
Console.WriteLine(memento2_state);

Вы заметите, что memento1_state и memento2_state различны, потому что они не совместно используют один и тот же базовый объект.

0 голосов
/ 25 марта 2020

Инкапсуляция не означает, что вы вообще не сможете получить доступ к данным, вы просто не должны иметь доступ к ним напрямую. Вы должны иметь возможность получить к нему доступ только через publi c методы:)
Эта ссылка, вероятно, сможет объяснить это лучше, чем я:

https://www.geeksforgeeks.org/encapsulation-in-java/

Таким образом, инкапсуляция сохраняется в вашем примере кода, так как состояние можно получить только с помощью метода get publi c get.

...