Design Pattern: Facade
The “Facade” concept focuses on decomposing a complex system into manageable sub-systems, each having its dedicated representative object also called “Facade”.
The pattern bears a resemblance to micro-service models often employed in large-scale web backend systems, where each micro-service's API serves as a representative.
Another usage is to let Facade plays the role of an interface with multiple implementations, symbolizing various sub-systems.
When to Use
- Simplifying Complexity: create a straightforward interface, making it easier for external entities to interact with complex underlying code. The Facade should be designed to be versatile enough for most common requirements. However, direct access to the code behind the Facade is still possible in rare cases where it is truly necessary.
- Managing Dependent Types: When various types are intricately dependent, rearranging them to go through the Facade can streamline dependencies. Instead of relying on N types, one can depend solely on the Facade.
Implementation
Structure
Sample Code
An example Facade interface can be written as follows in Go:
type StockManager struct {
readyStocks []ReadyStock
hotStocks []HotStock
}
func (s *StockManager) GetStock(item Item) int {
stock1 := findReadyStockOfItem(item, readyStocks)
stock2 := findHotStockOfItem(item, hotStocks)
return stock1 + stock2
}
The remaining code for sub-systems is omitted. We can still understand the pattern without it.
Testing
Given that this pattern primarily focuses on structuring types, testing is typically not required.
Related Patterns
Singleton
Often, only one Facade is needed. So we can apply the Singleton pattern ensures this uniqueness.
Abstract Factory
Since each sub-system contains inter-related objects, the Abstract Factory pattern can assist in their initialization.