Single Responsibility Principle: A class should be limited to a single responsibility. There should be one and only one reason to change a class.
- Supported by Object Composition (Composites), Strategy/Template Pattern etc.
- Key guidelines
- clearly defined boundaries as to where a piece of functionality is “implemented”;
- information-hiding in components that protect the integrity of data;
- separation of concerns that ensures changes in one location do not affect others;
Open/Closed Principle: Class should be open for extension but closed for modification.
- This is supported by Decorator pattern which allows:
- to dynamically add behaviours to an existing class
- incremental extension of target class and it’s decorators too
- uses composition and avoids class explosion
- Related patterns for decorator: Adapter, Composite, Facade, Bridge, Flyweight, Proxy
Liskov’s Substitution Principle: Subclasses can be substituted instead of their base class (OR interfaces). This ensures inheritance is used properly, we don’t build dependencies on subclasses but on abstract-tions (interfaces) and the system can fail gracefully. Also subtypes should not strengthen pre-conditions or weaken post-conditions.
Interface Segregation Principle: Interfaces should be client/consumer specific rather than being general.
Dependency Inversion Principle: Systems/classes should depend on abstractions instead of concretions.
- This is supported by IOC containers and Service Locator pattern.
Design patterns and their use cases:
Decorator Pattern: To dynamically add properties/behaviour onto classes without modifying them. These decorators are then substitutable for the classes they decorate.
Facade Pattern: To simplify a complex/poorly designed API (or SET OF APIs) by orchestrating/wrapping/aggregating interactions. e.g. Data Access facade (hides the multiple complex steps required to access data stores) – ADO.NET was a facade for RawSql ODBC. Or a FileSystem provider could be a Facade for an OS independent file system access (providing a simpler/abstracted API for an entire subsystem). However, we normally don’t have a strict facade interface to provide/expose. Is that strictness was mandated in for a facade, then that facade would also be an ADAPTER since it is adapting one interface to another(one or more). Related patterns: Adapter, Flyweight, Mediator.
WIDELY used patterns:
- MVVM, Decorator, Facade, Proxy, Service Locator, Adapter, Lazy Load, Abstract Factory, Iterator, Composite, Builder, Observer (events/delegates and or pub/sub), Repository, Singleton (IOC container is mostly instantiated as a singleton to manage registrations and object lifetimes), Strategy, Unit of Work (or Use Case pattern),