Design Patterns and Principles

Design Patterns and Principles

Introduction

This article is a cheat sheet of the most used design patterns and principles. This was not made to teach you. This was made to make you remember what you already understood.

Basic definitions

Several design patterns based on the following

Wrapper

Hold a reference to another object. Sometimes it means the owner manages the lifetime of that object sometimes just a simple reference.
To make it flexible this reference is mad through an interface instead of a particular class.

Delegation

Move to certain functionality of another class or use functionality of another class. Applicate it using the wrapper.

Factory

Factory is a class or method which has the only task to manage the creation of other classes. Th benefit of it is that different classes don’t have to take care of the classes. Factory usually provides objects through interface.

Interface

The interface is a structure of a class without a specific implementation. It is a contract between two objects. Specifies what methods an object can have – but does not specify the behavior. Different classes implements different behavior to the same interfaces.

 

GoF Patterns

GoF is the abbreviation of Gang of Four – after the four authors of one of the most fundamental design patterns book

Creational Patterns

Abstract Factory

“Provide an interface for creating families of related or dependent objects without specifying their concrete classes.”
Client uses a factory (referencing Abstract Factory) to create instances of different classes. Define an interface/class which declares the methods used by the client and add different implementation of it by overriding the creation methods. This way the client can build products with the same structure using the factory by calling the appropriate method.

Abstract Factory is often implemented using Template Methods or Prototype.

Builder

“Separate the construction of a complex object from its representation so that the same construction process can create different representations”
Director class
sets up a complex object by calling elementary methods defined in the Builder interface/class. Each builder subclass implements the operations in its own way so Director won’t know what parts makes
up the object and how are they assembled.

Factory method

“Define an interface for creating an object, but let subclasses decide which class to instantiate”
Put a dedicated method to a class (Creator) which creates the Product. Creator also can contain other methods which is used with Product. The subclass of Creator will implement the method and create the specific Product instance.

Prototype

Create new instances of a class using an existing one by cloning/copying it. Very useful, when the creation of new instances needs in runtime while the classes are referenced by an interface/base-class.

Singleton

“Ensure a class only has one instance, and provide a global point of access to it”
Instance of a class can be accessed through only one method (a static/class method) and keep the only instance inside the class scope. The allocation/creation of the class instance have to be prohibited to other classes.
Be careful and do not overuse this pattern. This is one of the anti-patterns. For more information why, see here (http://andras.palfi.hu/singleton-the-anti-pattern).

Structural Patterns

Adapter

Implement an interface for a class to make it compatible with another class which wants to use the first class.

Class adapter: use multiple inheritance/interface implementation to implement the new interface while subclassing the original class.
Object adapter: create a new class implementing the desired interface and encapsulate the original class holding reference to it in a member. In the interface-methods call the methods of the encapsulated class (see: delegation).

Bridge

“Decouple an abstraction from its implementation so that the two can vary independently”
You have a class hierarchy which performs complicated operations. Each operation in a subclass calls the existing simpler operations referencing the operations through and interface. On the very bottom of this hierarchy there are some very simple operations. This very simple operations base to be delegated to another base class or interface so each call of the basic operations will be forwarded to another class. By subclassing this delegated class you will have complex operations using the class hierarchy while you only have to implement very simple methods. Reimplementing the basic operations in a separate class gives you a different representation of the complex hierarchy.
For example: a drawing application which draws complex shapes (rect etc.) using the drawline method on the very base. If you implement the drawline to different OS-s your complex drawing is still the same but works on different platforms.

Composite

Compose objects to hierarchies by using a base class/interface which contains the very basic mandatory operations to manage the hierarchy and perform basic operations.
You will have node classes and leaf classes. Calling a basic operation on a node will forward the same call to all its children. Hierarchy management operations will works only on node items.

Decorator

Attach additional functionality to an existing component by wrapping it. For compatibility reason all the classes needs a base class/interface. All operations called on the decorator will be forwarded to the wrapped class but performing additional operations before and/or after the forwarded call.

Facade

To hide, simplify or control a complex class hierarchy create and publish a new class. Delegate all operation to the appropriate subsystem class.
Users of the facade don’t know about the subsystem classes and subsystems classes don’t know about the facade or the user classes.

Flyweight

Share the expensive objects between instances if there are numerous elements in a system which uses the same o almost the same classes. Do not store system-object specific states in the flyweights but pass the actual state to them on use.

Proxy

A placeholder for an object to control the access to it. Wrap the original object into the proxy and forward every call to it.

remote proxy: provides a local representation of a remote object in a different address space.
virtual proxy: create the wrapped object on demand – lazy binding
protection proxy: filter the access to an object
smart pointer: reference counting and lifetime management; thread locking

Behavioral Patterns

Chain of Responsibility

Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.

Command

Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.

Interpreter

Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.

Iterator

Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.

Mediator

Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interactions independently. The colleague objects don’t hold reference to each other but a reference to the mediator object (through an interface or abstract class). The mediator has reference to the more important colleague objects.

Memento

Without violating encapsulation, capture and externalize an object’s internal state so that the object can be restored to this state later. Serialization/deserialization.

Observer

Define a one-to-many dependency between objects. The observers listen to the changes of observed object (subject) so that when the subject changes its state, all its observers are notified and updated automatically.
Usually the subject send out specific messages which the observers catch/handle.

State

Use if there is a need to change the behavior of a class in runtime. The client class holds reference to the context class which is technically a proxy. The context class holds reference to a specific state object. If the state should change the context class sets its pointer to another state class.

Strategy

Encapsulate specific functionality into classes with the same interface. This way different operations or functionalities will be interchangeable.

Template method

Implement an operation using more steps. The subclasses have to add implementation of certain steps. For example opening document.

Visitor

Perform different operations on an object hierarchy. Visitor base class declares VisittXXX operations for all ConcreteElements in the object hierarchy (VisitConcrete1, VisitConcrete2). The ConcreteVisitor classes overrides the VisitXXX methods to perform the necessary operations. The Element base class declares the Visit(Visitor) method which the ConcreteElement classes override and the their Visit methods will call the appropriate VisitXXX method. This way you can define and perform different operations on a hierarchy (composite, list, etc).

Non GoF Patterns:

Multiton

Similar to singleton but usable for more different instances. A collection of singletons. Usually the different “singletons” can be access by a referencing key: string, enum, interface etc.

Principles

SOLID

Solid is an acronym for the following principles.

  • Single Responsibility Principle: a class should have only a single responsibility
  • Open Closed Principle: classes should be open for extension but closed for modification
  • Liskov Substitution Principle: derived classes must be substitutable for their base classes.
  • Interface Segregation Principle: make fine grained interfaces that are client specific. Many client specific interfaces are better than one general purpose interface.
  • Dependency Inversion Principle: depend on abstractions not on concrete implementations. There are high level and low level objects. High level uses the low level. The concept is that the high level should specify the interface which should be implemented by the low level (the writer methods of a logging interface should come from the higher level object and not specified for example by the FileWriter which contains file level attributes/properties)

Inversion of Control – IoC

Used to decouple different classes so the classes won’t reference each other but should use interfaces and will get the used instances on another way. (Belongs to the Dependency Inversion Principle)

Service locator/provider:

Instead of referencing (and creating) objets of specific classes use a special class which provides the necessary classes on runtime. The service locator usually provides long live objects but also can behave like a factory (or better if it uses one). The service locator is a proper substitution of the singleton pattern.

Dependency injection – DI:

pass the dependent objects to the user class on runtime

Constructor injection: pass as a parameter of the constructor
Setter injection: pass by calling a setter method
Interface injection: interface declares a setter like logic and should override the original class.

Separation of Concerns

TBD

GRASP

TBD

KISS

TBD

DRY

TBD

YAGNI

TBD

Other patterns, principles

Closure

Encapsulate sets of operations together with their context/used variables. Usually in the background the compiler generates a tiny class for you.

Lazy load/ Late binding

TBD

RAII

TBD

Opaque pointer/Pimpl idiom

TBD

Type Introspection

The ability of a program to check/get information of a class in runtime so the client can make decisions and perform different operations depending on the information of the referenced class.

Reflection

Type introspection + the ability to modify the structure and behavior of classes in runtime.

Presentation Patterns

Model-View-ControllerMVC

Controller has reference to the View and the Model, View can have a reference to the Model,

Model-View-PresenterMVP

Presenter has reference to the View and to the Model. The view doesn’t have reference to the model or to the Controller

Passive ViewMVP PV: the view no longer responsible for updating itself from the model.

Supervising PresenterMVP SC: view uses some form of Data Binding to populate much of the information for its fields, for complex interactions then the controller steps in.

PM

View has reference to the Presenter (presentation model), it doesn’t know about the view. Presentation model fires events what are handled by the View.

MVVM

PM with data binding.

Singleton – the Anti-Pattern

Avoid to use the Singletons – if possible

Everybody knows the singleton pattern. If you want to allow in an app to use only one instance of an object you implement a static/class method which provides the instance for the caller and deny any other allocation. While there are situations where this is the only solution (1%) it seems the pattern is highly overused and better to avoid it this way.
This approach introduces more problems than solves.

Drawbacks:

  • Classes depends on a particular class, not an interface (even if your method returns a reference to an interface you still have to use the class to access that method).  If you want a code which is flexible and testable you have to remove all direct dependencies to classes but the singleton just introduces new ones.
  • the singleton concept hurts the one class one concern rule: it has a functionality concern and also an object lifecycle concern.
  • The singleton doesn’t have an owner, nobody manages its life-cycle. The singleton’s owner is itself. You cannot control when and how it can releases from memory and it won’t release until the program run.
  • States: the singleton can have specific states but there are situations when you want to go back to the original state. With a regular object it’s quite simple, just release the old object and create a new. With a singleton you need some reset method and you have to be very careful: there is always something you forgot to set back to the original state. Moreover there can be living references to the singleton which thinks the reference still has the old state. This also causes problems.
  • You can have more concurrent operations even if you want to have just one at a time. But if the singleton starts a background operation on another thread or got a callback later it causes several problems. It’s quite hard to maintain with a singleton while much simpler using simple objects
  • It’s not necessarily impossible but harder to write a good unit test where you want to mock the singleton.
  • Synchronization needed in a multi-threaded environment. You have to take care of the locking of the mutator methods.

How to replace the singleton

 Passing an object as a parameter or setting a property is always clearer. It is the easiest way to mock and more readable for other developers. Dependency injection also a good solution against singleton. If you really need to access a global super object use a service locator/provider instead. It can be configured differently in the app and in the unit test and the different classes won’t directly depend on each other.

 

What’s the case with the real singletons

There can be situations where you really have to use a singleton (because you don’t have the source of the singleton etc). In this situations it’s better to create a simple proxy class (or a kind of service locator) which uses the singleton. This way you hide the original singleton class and can easily mock it in the test.

 

ObjC Properties vs iVars

About property and iVar usage in init/dealloc methods.

Technically one use properties if he wants to publish a member. Make it accessible and/or modifiable without exposing the structure of the class. Properties also allows you to run a code (accessors) when the property is set (setter method) or get (getter method) by someone.

Since Xcode @synthesize generates the getter/setter for a property automatically, private properties are started to use as a convenient way to store a reference by retaining/copying an object. Moreover it isn’t needed to explicitly define an ivar for a property. The iVar is automatically generated now.

The properties however can do some more than one expects. Of course it automatically deallocates the original object assigning a new value to it but also sends out KVO notifications and there can be additional code which run hitting the accessor.

Usage in init/dealloc is not recommended

There are more reasons why you shouldn’t have to call a property in Init/dealloc:

  • Subclasses have not yet been initialized or have already deallocated when init or dealloc methods execute, making accessor methods potentially unreliable
  • The setter can be an implemented method with other tasks or can be overridden in a descendant class and you never know what else will run calling the setter.
  • Moreover KVO notifications fire when the property changes and there can be listeners with additional code which also will run at that moment.

Either of them are desirable to run in a dealloc.