Design_Patterns.md 5.3 KB

Design Patterns

Introduction

  • General, reusable solution in a commonly occurring problem within a given context in software design
  • Patterns have been used for the longest times in architecture (Arches, doors, support structures)
  • The same applies to Software Engineering

Design Patterns - Elements of Reusable Objective-Oriented Software 1994

  • Still valid but other patterns and paradigms have been discovered since
  • Patterns you would come up with regardless just from experience
  • Put into a book, formally, to create a language around the patterns
  • Major Patterns: Creational, Structural, Behavioural
  • Added Patterns: Concurrency

Creational

Factory Method

  • Subclasses dictate the class instance created
  • Design patterns don't have to be implemented as-is
  • Useful to use slightly different approaches for similar problems
  • Simplify creation of objects with default arguments

Example

create_ipc_message

Object Pool Pattern

  • Many objects of same type that are expensive to instantiate: thread, file, workers
  • These objects are used often, but possibly for a short period of time

    Example

    Webserver wants each request to run in its own thread, but don't want to create a thread each time. Solution: Create a thread pool

Resource Acquisition is Initialization (RAII)

Idiom used in object-oriented, statically-typed languages.

Useful to make sure resources are released when an exception is thrown.

Mostly in C++

Singleton Pattern

  • Ensure class has one instance
  • Easily access the sole instance
  • Control instantiation
  • Restrict number of instances
  • Access a global variable
  • Private constructor - method to give you access to the one instance

Structural Patterns

Adapter: adapt interface per a given set of expectations Aggregate: Composite with methods for aggregation of children Bridge: decouple an abstraction from its implementation so they can vary Composite: free structure of objects where every object has same interface Decorator: Add additional functional to an object Extensibility: Facade Flyweight Marker Pipes and filters Opaque pointer Proxy These all adapt interfaces

Behaviour Patterns

Chain of Responsibility

Have a single request handled by several different objects/levels/systems etc

  1. Send a request
  2. Each of 3 handlers must perform an action

Example

Logger has 3 different possible loggers In calling code, instantiate logger and add the loggers with each their own log level When the logger is asked to a log a message, it will only call the loggers appropriate to the particular log level provided to the call

Works well with protocol stacks: send a message and it goes up or down the stack to the physical layer, and then goes back to the application layer

Command Pattern

Object wrapping a function. You give that object to be executed by someone else

Iterator Pattern

Class which has or is a container Instead of iterating through each element of the container, you have an interface which returns an object with a next() method which navigates to the subsequent element of that same container Abstraction layer over a container

Memento Pattern

Used in user interfaces Infamous Undo and Redo Memento has a state that can be stored. If you have a stack of memento, you can implement the logic to work through the stack of previous states

Subject Observer Pattern

AKA Observer Pattern

  • One to many dependency between objects defined without making objects tightly coupled
  • We don't know how many observers we will have on the subject
  • It should be possible that one object can notify an open ended number of objects Event loop with possible observers to receive events

State Pattern

  • Object should change its behaviour when internal state changes
  • State-specific behaviour should be defined independently

How:

  • Define separate state objects that encapsulate state-specific behaviour
  • Class delegates state-specific behaviour to its current sate object, instead of implementating state-specific behaviour directly

Visitor Pattern

Like chain of responsibility, but rather than a request going to a bunch of different objects, instead it's something which happens while visiting a certain structure

Concurrency Patterns

Active Object Pattern

Activeobject design pattern decouples method execution from method invocation for objects that reside in their own thread.

Command pattern is applied here.

Pattern consists of six elements:

  • Proxy providing interface towards clients
  • Interface with request() to active object
  • List of pending requests
  • Scheduler which decides which request to execute
  • Active object method
  • Callback or variable for client to receive the result

Double-checked Locking

See example in code

Concurrency Lock Pattern

If two threads can change bank balance, you are in trouble. Lock access to account balance

CPU Atomic Operation

Allows for locking of variable without a mutex Atomic operations cannot be interrupted by another thread Works with fundamental types (int, float) Made possible through Assembler call "Compare and Exchange" CMPXCHG Modern languages support this and take care of calling the right Assembler instruction Checks the value of a variable and then sets its value in a single operation without the possibility of being interrupted

static std::atomic_bool exiting(false);
if (exiting.exchange(true)) return;