Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Applied Java™ Patterns - Stephen Stelting, Olav Maassen.pdf
Скачиваний:
202
Добавлен:
24.05.2014
Размер:
2.84 Mб
Скачать

State within the Memento should be inaccessible to everybody except the Originator.

StateHolder – The object that wishes to preserve the state. It never needs to know what is within a Memento; it only needs to know that the object it receives enables it to restore the state of the Originator.

Because the Memento should be accessible only to the Originator, it is best to make the Memento a public inner class in the Originator. All the methods are declared private so they are only available to the Memento and its enclosing class, thus providing the appropriate encapsulation.

Instances of an inner class are always associated with an instance of the outer class. This is necessary because an inner class always has access to instance variables of the outer class. That causes a problem in this situation; the Memento should be independent of a specific instance of an Originator. Therefore the Memento class needs to be a static inner class.

Memento objects can become very large, especially if the Originator keeps all its state in the Memento and Mementos are created frequently. To compensate for this, you can change Mementos so that they record only changes in state since the previous creation of a Memento. The state holder has to keep track of the order of the Mementos. Job promotions are an example of when you might apply this. After every promotion your employee benefits and salary are changed based on the previous salary, and you may get a new boss, new department or a bigger car. Now every Memento of your employee benefits only needs to record the increase or decrease in conditions/salaries since the last Memento.

Benefits and Drawbacks

Using the Memento pattern has the following consequences.

Preserves encapsulation – Even when the state of the Originator needs to be stored outside of the Originator object in a client, the state is inaccessible to the client. It has a reference only to the Memento object, and no way to access the information that’s inside. It also makes the client simpler because it no longer needs to know anything about the internal workings of the Originator, except how to get a Memento and how to use it.

Simpler Originator – Suppose the Originator has to keep track of all the different states. The Originator would soon become very bloated and very difficult to handle. It is much easier to give that responsibility to the requesting party, the client. The Originator now only needs to be able to create and use Mementos instead of keeping track of multiple states.

Expensive Mementos – Mementos are very expensive to create if every piece of the Originator’s state has to be stored in the Memento. This increases dramatically as the Originator increases in size. This is where the incremental changes are important. If the Originator is large, Memento might not be a suitable pattern.

Expensive Memento storage – The state holder is responsible for the life-cycle management after it receives the Memento from the Originator. However, it does not know how large the Memento actually is. If Mementos are not kept as small as possible, the StateHolder will pay the price.

Pattern Variants

Pattern variants include the following:

If the Memento must be a standalone class, and not an inner class, you must define two interfaces: WideMemento and NarrowMemento. The wide interface is for the Originator of the Memento so that it can access the Memento to get its state. The state in the Memento is best set at construction time. Because you’re defining an interface, you’ll need to add a FactoryMethod.

The narrow interface is intended for the StateHolder and other clients to use. If that interface doesn’t have any methods, the NarrowMemento becomes obsolete and the interested parties only refer to the Memento as an Object.

To be able to extend the Originator but not need to change the Memento code, the methods can have package access instead of being private. This allows subclasses of the Originator to use the same Memento class.

Related Patterns

Related patterns include the following:

65