Structural Design Patterns in System Development
By Marcelo Vieyra, October 31st 2023 | 3 mins, 512 words
Structural design patterns deal with the composition of classes and objects to create larger structures. They address concerns such as object composition, interface simplification, and the creation of flexible class hierarchies. Some of the most commonly used structural patterns include:
1. Adapter Pattern
The Adapter pattern allows incompatible interfaces to work together. It involves creating a wrapper class that acts as an intermediary to allow two interfaces to collaborate effectively. Here's an example in PHP:
interface Target { public function request(); } class Adaptee { public function specificRequest() { return "Adaptee's request."; } } class Adapter implements Target { private $adaptee; public function __construct(Adaptee $adaptee) { $this->adaptee = $adaptee; } public function request() { return $this->adaptee->specificRequest(); } }
2. Bridge Pattern
The Bridge pattern separates an object's abstraction from its implementation so that they can vary independently. It promotes loose coupling between an abstraction and its implementation. Here's an example in PHP:
interface Implementor { public function operationImp(); } class Abstraction { protected $implementor; public function __construct(Implementor $implementor) { $this->implementor = $implementor; } public function operation() { return "Abstraction: " . $this->implementor->operationImp(); } } class ConcreteImplementorA implements Implementor { public function operationImp() { return "Concrete Implementor A"; } }
3. Composite Pattern
The Composite pattern allows you to compose objects into tree structures to represent part-whole hierarchies. It's particularly useful when you need to work with individual objects and compositions of objects uniformly. Here's an example in PHP:
abstract class Component { public abstract function operation(); } class Leaf extends Component { public function operation() { return "Leaf"; } } class Composite extends Component { private $children = []; public function add(Component $component) { $this->children[] = $component; } public function operation() { $result = "Composite: "; foreach ($this->children as $child) { $result .= $child->operation() . " "; } return $result; } }
4. Decorator Pattern
The Decorator pattern allows you to add behavior to individual objects, either statically or dynamically, without affecting the behavior of other objects from the same class. Here's an example in PHP:
interface Component { public function operation(); } class ConcreteComponent implements Component { public function operation() { return "Concrete Component"; } } class Decorator implements Component { protected $component; public function __construct(Component $component) { $this->component = $component; } public function operation() { return $this->component->operation(); } } class ConcreteDecoratorA extends Decorator { public function operation() { return "Concrete Decorator A (" . parent::operation() . ")"; } }
5. Facade Pattern
The Facade pattern provides a simplified interface to a set of interfaces in a subsystem, making it easier to use and understand. It acts as a high-level interface that makes the subsystem more accessible. Here's an example in PHP:
class SubsystemA { public function operationA() { return "Subsystem A operation"; } } class SubsystemB { public function operationB() { return "Subsystem B operation"; } } class Facade { private $subsystemA; private $subsystemB; public function __construct() { $this->subsystemA = new SubsystemA(); $this->subsystemB = new SubsystemB(); } public function operation() { $result = "Facade initializes subsystems:\n"; $result .= $this->subsystemA->operationA() . "\n"; $result .= $this->subsystemB->operationB() . "\n"; return $result; } }
Conclusion
Structural design patterns play a crucial role in system development, allowing developers to create flexible and maintainable systems. These patterns help in achieving a high level of code reusability and ensuring that changes can be made with minimal impact on the existing codebase. By understanding and applying these structural patterns, you can improve the organization and efficiency of your software projects.