Link Search Menu Expand Document

Structural Design Patterns

In this tutorial, we will learn about “Structural Design Patterns” which offers solutions for organizing the structure of the relationship between objects in Object-Oriented Programming with Java.

First, we define structural design patterns, we explain when to use them, and then describe best known and frequently used structural patterns which are as follows: Adapter, Bridge, Composite, Decorator, Facade, Flyweight, Proxy. Lastly, we summarize the tutorial.

What are Structural Design Patterns stand for?

Structural patterns form design patterns together with Creational and Behavioral patterns. It allows us to establish larger software groups by combining classes and objects. Following the class and object structures in Java, structural patterns are divided into two groups as “Class patterns” and “Object patterns”.

Class patterns expand the structures in software projects by combining class interfaces or applications by using inheritance. Object patterns help users to create new objects by combining existing objects so that the objects gain properties.

There are 7 various situations that software engineers use Structural Design Patterns in their projects. Structural patterns can be used in the design stages or the expansion stages of the projects.

Adapter

The purpose of the adapter pattern is to convert the interface of one class to the expected interface by another class. We often want to use a combination of classes developed with different structures. This means that they have a fundamentally different interface from the usage point of view. The adapter allows classes to work that can not work together due to their incompatible interfaces.

Bridge

This pattern is used to separate abstraction and implementation into class hierarchies. There is a class upon both the abstraction part and the implementation part. These two hierarchies are interdependent. Here, the pattern is named as a “Bridge” between the two parts. In the abstraction part, there are higher-level operations of the system. In the implementation part, there are simpler operations that are related to these higher-level operations and detail them.

An example of usage for the Bridge pattern is given below.

abstract class Vehicle {
protected Workshop workShop1;
protected Workshop workShop2;
 
protected Vehicle(Workshop workShop1, Workshop workShop2)
{
this.workShop1 = workShop1;
this.workShop2 = workShop2;
}
 
abstract public void manufacture();
}

 
// Refine abstraction 1 in bridge pattern
class Car extends Vehicle {
public Car(Workshop workShop1, Workshop workShop2)
{
super(workShop1, workShop2);
}

 
@Override
public void manufacture()
{
System.out.print("Car ");
workShop1.work();
workShop2.work();
}
}

 

// Refine abstraction 2 in bridge pattern
class Bike extends Vehicle {
public Bike(Workshop workShop1, Workshop workShop2)
{
super(workShop1, workShop2);
}

 
@Override
public void manufacture()
{
System.out.print("Bike ");
workShop1.work();
workShop2.work();
}
}

 

// Implementor for bridge pattern
interface Workshop
{
abstract public void work();
}

 
// Concrete implementation 1 for bridge pattern
class Produce implements Workshop {
@Override
public void work()
{
System.out.print("Produced");
}
}

 
// Concrete implementation 2 for bridge pattern
class Assemble implements Workshop {
@Override
public void work()
{
System.out.print(" And");
System.out.println(" Assembled.");
}
}

 

// Demonstration of bridge design pattern
class BridgePattern {
public static void main(String[] args)
{
Vehicle vehicle1 = new Car(new Produce(), new Assemble());
vehicle1.manufacture();
Vehicle vehicle2 = new Bike(new Produce(), new Assemble());
vehicle2.manufacture();
}
}

Output

Car Produced And Assembled.

Bike Produced And Assembled.

Composite

The purpose of this pattern is to arrange the objects as a tree structure and establish the relationship between the top and bottom. The top and bottom objects in the tree structure derive from the same interface class and resemble each other. That is, the client behaves in the same way with the leaf object and the parent object. Thus, it becomes easier to express and operate on hierarchy. It also becomes easy to add new objects to the hierarchy.

Decorator

This pattern is used to add properties to the object. The parent object is unaware of adding these properties, no code changes are required on this object. In other words, this pattern is used to dynamically add new attributes to an object without creating subclasses.

Facade

This design pattern hides the details of the system and offers a single front face for the client to access the system from the outside. This front face reaches the subclasses in the system. The client knows only this class of frontend in the system.

Flyweight

A flyweight pattern is used when there are many objects in the system to prevent the number of objects to cause problems. Because the cost of using a large number of objects is high. It is necessary to keep lightweight objects in a collection. If the states of these objects are low, the number of common objects is reduced. Thus, the size of this collection is also reduced.

Proxy

It enables us to hide the physical location of the object to be used by the user.

Summary

We start from the definition of structural patterns. First, we explain the “Adapter” which converts specific interfaces to compatible with other classes. After that, we mention the “Bridge” pattern that allows us to arrange both the interface and the application separately from each other.

Then we explain the “Composite” pattern that puts objects in an order with the tree structure and reaches this structure from a single interface. Next, we mention the “Decorator” pattern, it allows us to add new responsibilities to an object without changing it.

“Facade” pattern allows a complex structure to be kept together and used over a single interface. “Flyweight” pattern allows us to create a crowded object structure by creating visual objects from a sample object, rather than creating a large number of similar objects.

Finally, the “Proxy” pattern hides the physical location of the object from the user.

Other useful articles:


Back to top

© , Java Interviews — All Rights Reserved - Terms of Use - Privacy Policy