Encapsulation is a cornerstone of object oriented design. But OOLs generally only provide direct support for encapsulating data together with methods that manipulate and provide controlled access to the data. Complex programs often need multiple levels of encapsulation. These higher levels of encapsulation can be provided by encapsulation design patterns. Encapsulation design patterns can do one of two things:
Sometimes you want to encapsulate a group of classes in order to implement an abstract view of their combined functionality. Often when this is done you may still want to be able to be able to access the classes directly.
Facade - provides a unified interface to a set of interfaces in a subsystem making it easier to use.
Examples: JTable, JTree, JEditorPane. Each of these examples combines an implementation of JComponent methods with Facade constructors and methods whose abstract view hides complex model, view, and controller classes.
Sometimes you just want to define an abstract behavior that has several variations. That is, you want to encapsulate several algorithms that share a common interface to make them interchangeable.
Strategy - defines a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.
Examples: Swing layout managers.
Sometimes you need to relax encapsulation at a low level in order to do a better job of encapsulation at a higher level. Although this sounds contradictory, the improvement arises from the fact that allowing higher level classes to directly access data in lower level classes or vice-versa avoids having to declare public methods for the access.
For this reason, well-designed OOLs have mechanisms that allow one class to have access to private members of another class. In C++, for example, you can declare one class as a "friend" of another class. In Java, a class can be nested inside of another class, which allows both classes to access private members of the other class.
Observer - often provides a public method for modifying an object that it has private access to, but another object (a Subject) decides when the modification will occur.
Example: Swing listeners.
Iterator - provides sequential access to objects in an Aggregate without exposing the implementation of the Aggregate.
Examples: java.util.Iterator objects for java.util.Collection classes.
Memento - carries state information about an Originator object, allowing the Originator private access to that information. In many cases a Memento has no public interface at all. Clients can get a Momento from an Originator but the only thing they can do with it is pass it as a parameter in a message sent to the Originator.
Example: often used to support "undoable" operations in editors. The Memento object records information about the state of the document that is being edited. The editor restores this state to undo an earlier operation.