//
import CodeBlock from '@/components/mdx/CodeBlock'
import Tip from '@/components/mdx/Tip'
import Terminal from '@/components/mdx/Terminal'
import OutputBlock from '@/components/mdx/OutputBlock'
export const meta = { title: 'Introduction to Structural Patterns', description: 'Overview of structural patterns and their use cases.', lastUpdated: '2026-05-15', readTime: '10 min read', order: 11 }
# Introduction to Structural Patterns
## Introduction
In software design, **structural patterns** are concerned with how classes and objects can be composed to form larger structures. These patterns provide flexible solutions for building complex systems by defining ways to compose objects into more complex ones while keeping the system organized and maintainable.
Structural patterns help in managing relationships between different parts of a system, making it easier to extend or modify without affecting other components. They are particularly useful when dealing with large codebases where modularity and scalability are crucial.
## Concept
### What Are Structural Patterns?
Structural patterns focus on the composition of classes and objects to form larger structures. They help in defining how different classes interact with each other, often by creating new interfaces or modifying existing ones. Some common structural patterns include:
1. **Adapter Pattern**: Allows incompatible interfaces to work together.
2. **Bridge Pattern**: Separates an abstraction from its implementation so that the two can vary independently.
3. **Composite Pattern**: Composes objects into tree structures to represent part-whole hierarchies.
4. **Decorator Pattern**: Adds new functionality to an existing object without altering its structure.
5. **Facade Pattern**: Provides a simplified interface to a complex subsystem.
6. **Flyweight Pattern**: Reduces memory usage by sharing common data among multiple objects.
### Use Cases
Structural patterns are widely used in various scenarios:
- **Modular Design**: When you need to build systems that can be easily extended or modified without affecting other parts.
- **Interoperability**: When different components with incompatible interfaces need to work together.
- **Memory Optimization**: When memory usage needs to be minimized by sharing common data.
## Examples
### Adapter Pattern Example
The Adapter pattern allows objects with incompatible interfaces to collaborate. It acts as a mediator between two incompatible interfaces, converting the interface of one class into another that clients expect.
#### Code Example
```javascript
// Target interface expected by the client
class MediaPlayer {
play() {}
}
// Adaptee class with an incompatible interface
class AudioPlayer {
listen() {
console.log('Playing audio...');
}
}
// Adapter class that implements the target interface and uses the adaptee
class MediaAdapter extends MediaPlayer {
constructor(adaptee) {
super();
this.adaptee = adaptee;
}
play() {
this.adaptee.listen();
}
}
// Client code
const audioPlayer = new AudioPlayer();
const mediaPlayer = new MediaAdapter(audioPlayer);
mediaPlayer.play(); // Output: Playing audio...
listen method.AudioPlayer to the MediaPlayer interface by implementing the play method and calling the listen method of the adaptee.The Composite pattern allows you to compose objects into tree structures to represent part-whole hierarchies. It lets clients treat individual objects and compositions of objects uniformly.
// Component interface
class Graphic {
draw() {}
}
// Leaf class representing a simple shape
class Circle extends Graphic {
draw() {
console.log('Drawing a circle...');
}
}
// Composite class representing a group of shapes
class Group extends Graphic {
constructor() {
this.children = [];
}
add(child) {
this.children.push(child);
}
draw() {
console.log('Drawing a group:');
this.children.forEach(child => child.draw());
}
}
// Client code
const circle1 = new Circle();
const circle2 = new Circle();
const group = new Group();
group.add(circle1);
group.add(circle2);
group.draw();
// Output:
// Drawing a group:
// Drawing a circle...
// Drawing a circle...
draw method.Graphic objects. It implements the same draw method but iterates over its children to draw them.In the next section, we will dive deeper into the Adapter Pattern and explore more practical examples of how it can be used in real-world applications. Understanding the Adapter pattern is crucial for creating flexible and interoperable systems.