Design Patterns · Part 3 of 4

Introduction to Structural Design Patterns

Tisan Das · · Updated · 3 min read

Contents

    In the last blog post, we’ve explored on the creational design patterns. In this blog post, we would explore a different set of design patterns: the structural ones. The structural design patterns are concerned with how classes and objects are composed to form even larger structure. The primary objective here is to compose the components in a flexible and extensible way, so that change can be made in specific parts of the structure without changing the entire structure.

    Adapter Pattern:

    Intent: Covert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn’t otherwise due to incompatible interfaces.

    Class Diagram:

    Class Diagram: adapter Class Diagram: adapter Class Diagram: adapter

    Implementation:
    Go
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    
    package adapter
    
    import (
    	"fmt"
    )
    
    // -- Adaptee ---
    type Adaptee interface {
    	SpecificRequest()
    }
    
    func NewAdaptee() Adaptee {
    	return &adaptee{}
    }
    
    type adaptee struct{}
    
    func (adptr *adaptee) SpecificRequest() {}
    
    // -- Target ---
    type Target interface {
    	Request()
    }
    
    func NewTarget() Target {
    	return &target{}
    }
    
    type target struct{}
    
    func (tgt *target) Request() {}
    
    // -- Adapter ---
    
    func NewAdapter() Target {
    	return &adapter{adaptee: NewAdaptee()}
    }
    
    type adapter struct {
    	adaptee Adaptee
    }
    
    func (adpt *adapter) Request() {
    	fmt.Println("Using the requesst specific method for adaptee!")
    	adpt.adaptee.SpecificRequest()
    }
    

    Bridge Pattern:

    Intent: Decouple an abstraction from its implementation so that it can vary independently

    Class Diagram:

    Class Diagram: bridge Class Diagram: bridge Class Diagram: bridge

    Implementation:
    Go
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    
    package bridge
    
    import (
    	"fmt"
    )
    
    type Abstraction interface {
    	Operation()
    }
    
    type Implementor interface {
    	OperationImp()
    }
    
    func NewRefinedAbstraction(imp Implementor) Abstraction {
    	return &refinedAbstraction{imp: imp}
    }
    
    type refinedAbstraction struct {
    	imp Implementor
    }
    
    func (abs *refinedAbstraction) Operation() {
    	abs.imp.OperationImp()
    }
    
    func NewConcreteImplementorA() Implementor {
    	return &ConcreteImplementorA{}
    }
    
    type ConcreteImplementorA struct{}
    
    func (impl *ConcreteImplementorA) OperationImp() {
    	fmt.Println("Inside operationImp of concrete implementor A")
    }
    

    Composite Pattern:

    Intent: Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.

    Class Diagram:

    Class Diagram: composite Class Diagram: composite Class Diagram: composite

    Decorator Pattern:

    Intent: Attach additional responsibilities to an object dynamically. Decorator provides a flexible alternative to subclassing for extending functionality.

    Class Diagram:

    Class Diagram: decorator Class Diagram: decorator Class Diagram: decorator

    Facade Pattern:

    Intent: Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.

    Class Diagram:

    Class Diagram: facade Class Diagram: facade Class Diagram: facade

    Flyweight Pattern:

    Intent: Use sharing to support large numbers of fine-grained objects efficiently.

    Class Diagram:

    Class Diagram: flyweight Class Diagram: flyweight Class Diagram: flyweight

    Object Diagram:

    Object Diagram: flyweight Object Object Diagram: flyweight Object Object Diagram: flyweight Object

    Proxy Pattern:

    Intent: Provide a surrogate or placeholder for another object to control access to it.

    Class Diagram:

    Class Diagram: proxy Class Diagram: proxy Class Diagram: proxy

    Object Diagram:

    Object Diagram: proxy Obj Object Diagram: proxy Obj Object Diagram: proxy Obj

    References:

    1. Design Patterns: Elements of Reusable Object-oriented Software
    2. Structural Design Pattern

    Open mail app

    Write in Gmail · Outlook