Following the course of Joe Marini on Go Design Patterns
- Builder
- Factory
- Singleton
Purpose:
Encapsulates an object's construction process along with specifying the various parts of a complex API
Enables flexible creation of an object that can have many different representations
Increases code readability for complex types
Scenarios:
Objects that have complex APIs, multiple constructor op`tions, and several different possible representations
new() create()
Director ------> Builder ----------> Complex Object
newBuilder() setPropA()
setPropB()
setPropC()
create()
Advantages:
- Encapsulation of the construction of the internal representation of the complex object
- Builder provides detailed control over how object is constructed
Disadvantages:
- Creating a builder for each type of complex object
- Cause some difficulty to other software engineering techniques like dependency injection
- Each object must be a mutable object which might not always be desirable
Purpose:
Allows for the construction of objects when the types of those objects is not predetermined at runtime
Scenarios:
Produces code that is more readable when there are multiple ways of creating a particular object
Situations where object creation needs to be flexible and cannot be known beforehand
Product
Creator interface ---------> Product
+ factoryMethod()
^
|
| Create
Concrete Creator ---------> Concrete Product
+ factoryMethod()
Go has no inheritance. Go has the notion of interfaces and structs so we can use these to design a factory pattern.
Purpose:
Restricts instantiation of a class to a single instance and provides global access
Allows lazy initialization of the class. Not instantiated until it's needed.
Scenarios:
Situations where you want to ensure there is only one instance of a class: logging, configuration, telemetry, debugging
+---------------------------+
| Singleton |
| instance: Singleton |
| - Singleton() |
| |
|+ getInstance(): Singleton |-----------> return instance
+---------------------------+
In Go:
- Implement Singleton using structs
- Make sure to Singleton is safe to access from within go routines
Allows the interface of an existing subsystem or API to be used as another interface without modifying the code of the existing API.
Working with:
- Legacy systems
- API or subsystems that you don't have ownership of and can't make any changes too
Scenarios:
Enables incompatible objects to work together without having to make changes to either one
Purpose: Provide a simple, front-facing interface to a more complex system, library, or API
Scenarios:
- Improve usability of a more complex API.
- Serve as a starting point for refactoring.
- Reduce tight coupling between parts of a system for easier swapping out of components of functionalities as requirements change.
+-- Facade -----+ Subsystem
[ Client 1] |simpleAPI1() { | [Class A]
| funcA1() | funcA1()
| funcB2() | funcA2() [Class B]
|} | funcB1()
[ Client 2 ] |simpleAPI2() { | funcB2()
| funcC1() | [Class C]
| funcC2() | funcC1()
|} | funcC2()
+---------------+
Subsystem might be very complex. Do not want to expose all the complexity to the rest of the application.