Design Patterns Flashcards
(8 cards)
When possible, one should prefer _____ over inheritance.
“Composition”
A has-a relationship between objects, where one holds a reference to the other, is preferable over the baggage of an is-a relationship.
Whenever we design a system, we want to _____ what varies, so that we can limit the number of points of maintenance.
“Encapsulate”
This is a primary principle, and perhaps THE primary principle of OOP.
Parts of a system need to interact with one another, but we should strive for all interactions to be _____ _____.
“Loosely Coupled”
One common way to accomplish this is to program to an interface, and abstract away concrete implementations.
We should always strive to program to an _____, not an implementation.
“Interface”
This helps to keep our code loosely coupled, and open to extension.
Definition of the Open-Closed Principle,
and some patterns that support it.
“Classes (and as much code as possible, really), should be open for extension, and closed for modification.”
In essence, as requirements and features change, we don’t want to modify older code that other code might depend on. We want to be able to extend it, without making any changes.
There are numerous patterns to support this, but chief among them are:
- The Decorator Pattern
- Strategy Pattern
- Factory Pattern
- Observer Pattern
The crux of all of these is keeping code loosely coupled by programming to interfaces, and preferring composition (flexible at runtime!) over inheritance.
Abstract Factory Pattern
Provides an interface for creating families of related or dependent objects without specifying their concrete classes.
e.g. A class that creates a view could rely on an abstract StyleFactory, which has abstract methods for creating a font, headers, borders, etc. Concrete implementations of this StyleFactory that change the view considerably can simply be switched in and out at will, at runtime, and the client only has to know about the StyleFactory interface and be composed with a concrete StyleFactory implementation at runtime.
The Decorator Pattern
Attaching additional functionality and responsibility to an object dynamically by creating wrappers that implement the same interface as the wrapped object.
Decorators provide a flexible alternative to subclassing for extending functionality.
The principle idea is to create an object that implements the same interface as the object it wraps, and holds a reference to the wrapped object. When a method is called on the Decorator/ Wrapper, it is effectively intercepting that call. It can substitute the logic by returning something new, or add to it by calling the wrapped object’s method and add to the result. This way you have building block concrete subclasses of the super class, as well as an abstract decorator class that implements the superclass, which can be subclasses to create any number of decorators to wrap the building blocks; and even wrap each other!
The Observer Pattern
A one to many dependency between objects so that when the state of one object changes, all of its dependents are notified and updated automatically.
This is called by several names, including “Publisher-Subscriber” (pub-sub), Observables and Observers, Subject and Observers, Emitters and Listeners… etc.
Typically, the Publisher object holds a list of Objects that implement the appropriate Subscriber/ Observer interface, and whenever it’s state changes (what changes matter are determined by the object), it calls a method like “update()” on every Subscriber in the list to alert them to the change. The Subscribers hold a reference to a Publisher (composed with a concrete implementation at runtime) which allows them to call methods to register themselves as currently listening, un-register, and possibly call for specific information through getters on the Subscriber (“pull-style” observing, which is the favored mode).