Structural Design Patterns

Beyza Celep
19 min readApr 7, 2021

Hello,

In this post, I am going to talk about Structural Design Patterns : Adapter, Composite, Proxy, FlyWeight, Facade, Bridge, Decorator. You can find the explanations and code examples for each of them below. Before leading in, I want to talk about structural patterns.

Structures are one of the bases of coding. They effect performance, readability and stability directly. That’s why it is important to analyze the processes before starting development : finding best structure and algorithm that is going to be fast, easy to read-write operations, SOLID and flexible for the future. As I mentioned in my previous posts, design patterns are all about creating general solutions to common problems or scenarios and they are grouped by the objects’ functionalities. So, in the structural patterns, our main goal is to avoid problems and not to write repeated codes, making the structure or process of creation the structure more handy, easy. We use structural patterns to create a building that is ok for change, ok for implementation of other resources. Our keywords that I have used a lot while creating this post also summarizes what we use structural patterns for are : implementation & extendable functionality.

In structural patterns interfaces, abstract classes and inheritance is quite important. So, in case you would like to take a look, I am leaving some of my favorite links for each of them.

Adapter Pattern

Basically, Adapter helps client to use incompatible objects and our key words for adapter (wrapper) pattern are : composition / collaboration. What I want to say is, when 2 incompatible object can’t communicate, the adapter wraps an interface that talks same language with both of them and helps client to use the incompatible objects with this adapter. That’s why adapter pattern is also called wrappers. This incompatibility is generally caused by legacy or external code. Of course, we can also solve the problem by refactoring the code but sometimes refactoring is not possible, costs so much time or causes complexity. So we can also define adapters by saying : helps client to communicate necessary classes when they are incompatible and hard to refactor. You see, it just wraps the behavior to isolate the class.

In structural design patterns, the general logic and point of needs are : existing classes are incompatible with client, inheritance or implementation is complex, costs too much time and performance. So, the all structural patterns that are in this article you are going to see they do some kind of wrapping with different approaches or methods to solve these problems. Adapter is first of them, it wraps the method, functionality etc. that client needs but can’t use and make them usable. Some specific scenarios that we use Adapter Pattern :

-An existing class is necessary but its interface is not exactly what you need

-An existing object should be used in an environment which doesn’t fit with the object’s interface,

-If we want to create reusable class which can collaborate with incompatible classes.

https://levelup.gitconnected.com/design-patterns-structural-patterns-of-design-classes-and-objects-79d58a6519b

Now, I coded a very basic adapter pattern example just to make the purpose and implementation process of adapter pattern crystal clear. But I am leaving some of best-practices below, they are accessible from the links, if you are interested.

https://dzone.com/articles/design-patterns-explained-adapter-pattern-with-cod

In my own basic scenario, I have a class : ExistingReportTable. This class includes CreateReportDataTable() and create a report data table for my application.

namespace AdapterPattern
{
public class ExistingReportTable
{
public DataTable CreateReportDataTable()
{
//I create the datatable I needed, don't worry about the operations. Main concern is to implement Adapter Pattern.
DataTable x = new DataTable();
return x;
}
}
}

But as my app is using by many customers, I want to create report data tables with some different specific report datas and formats that are incompatible with current ones. So, I am going to create an Adapter and make them usable for the client.

 public interface IReportDataAdapter
{
public DataTable CreateReportData();
}

And now, the adapter :

public class ReportDataAdapter : IReportDataAdapter
{
public DataTable CreateReportData()
{
//I have created the necessary interface, now I am creating the Adapter itself.
ExistingReportTable reportTable = new ExistingReportTable();
return reportTable.CreateReportDataTable();
}
}

In Program.cs file :

class Program
{
static void Main()
{
//As you can see, the client is able to create the report table due to adapter pattern.
IReportDataAdapter adapter = new ReportDataAdapter();
var reportTable = adapter.CreateReportData();
Console.Write(reportTable);
}
}

Composite Pattern

As the name indicates, composite pattern composes the objects and help us to use them as a single object. The Composite pattern composes the objects as a tree : a tree means a hierarchical structure. This tree composition of objects can be use either as a single object or separate objects. Yes, this is the point : client can either use objects as a composition or separately and this makes things effortless.

So, when to use composite pattern ? If our application has parts where the objects are in hierarchical structure and we want to modify some of the similar ones, instead of applying same operations separately but again and again, we detect the objects that are in the same group, compose them. After that, when we do the modification that our application needed, we didn’t make things and of course the code more complex and we didn’t caused the repetitive code which is in the opposite of clean code approach and SOLID principles. By representing complex objects as a tree, we just make the whole app more tidy and readable.

You may intend that, composite pattern abstracts some behaviors of objects, union them in another object and represent as a tree to the client. So now, we can do some specific definitions about the structure and create the UML diagram before passing to the code implementation :

https://en.wikipedia.org/wiki/Composite_pattern

-Component : Component is a base for all objects that are exist in the hierarchy. Include the common properties, functionalities etc. to a class for all objects’ usage . In this case of course, the class is going to be abstract or an interface also can be used.

To create the component, we need to determine correctly what are these common points.

-Leaf : Leaves are objects that can not have a child object. They have exact same meaning that they have in tree structure. For more info :

https://www.cs.cmu.edu/~clo/www/CMU/DataStructures/Lessons/lesson4_1.htm

  • Composite : Yes, here we are going to do the necessary composition which means this is going to include informations or operations for both kind of objects.
  • After the creation of UML diagram with some theoric info, you can find an easy to-understand code implementation below :
  • Components : IPosition
  • Leafs : Attack,Defense,Midfield.
  • Composite : PositionCompositePattern.
namespace CompositePattern
{
public interface IPosition
{
public string PositionName { get; set; }
public void Render(double percentageOfPerformance);
}
public class Attack : IPosition
{
public Attack(string _positionName)
{
PositionName = _positionName;
}
public string PositionName { get; set; }
public void Render(double percentageOfPerformance)
{
//
}
}
public class MidField : IPosition
{
public MidField(string _positionName)
{
PositionName = _positionName;
}
public string PositionName { get; set; }
public void Render(double percentageOfPerformance)
{
//
}
}
public class Defence : IPosition
{
public Defence(string _positionName)
{
PositionName = _positionName;
}
public string PositionName { get; set; }
public void Render(double percentageOfPerformance)
{
//
}
}
public class PositionCompositePattern :IPosition
{
public PositionCompositePattern(string _positionName)
{
PositionName = _positionName;
}
public string PositionName { get; set; }
private readonly List<IPosition> positionList = new List<IPosition>();
public void Render(double percentageOfPerformance)
{
foreach(var item in positionList)
{
item.Render(percentageOfPerformance);
}
}
public void AddPosition(IPosition position)
{
positionList.Add(position);
}
public void RemovePosition(IPosition position)
{
positionList.Remove(position);
}
}
class Program
{
static void Main(string[] args)
{
//Now, it is possible to work with any type of position that implements IPosition interface !
PositionCompositePattern newPosition = new PositionCompositePattern("New Position");
Attack position1 = new Attack("Position1");
newPosition.AddPosition(position1);
Defence position2 = new Defence("Position2");
newPosition.AddPosition(position2);
position1.Render(56.95);
}
}

I have a base called Position which has common properties and functionalities for these three positions : Attack,Defense,Middle Player. At any time, any other positions can be created. At the beginning of the scenario assume that we do not use Composite pattern. What we have to do for accessing, creating, modifying or trying to create a more complex position and even in some scenarios using one of three existing positions, is to use them separately and repeat all the transactions for each. Now, you can see the advantage of using Composite pattern.

You may try to code without using Composite Pattern first to understand more deeply, which I did while studying and worked very well for me :)

Proxy Pattern

Again, the name indicates all : proxy , deputation and our key is : controlling the access. This pattern helps us to reach and control the resource object/class through another object but the resource’s itself. We are basically creating a bridge to resource that we want to access for any reason (ex.:for a service). Client doesn’t call the object directly, calls proxy. This proxy have the same responsibilities and authority as the resource object/class has. What does it mean that client accesses the proxy instead of resource ? Well, here is the key point: we create a smaller object rather than a complex and bigger one -> which means loosing couples in & between our application(s) and increasing the complexity.

https://ar.pinterest.com/pin/365284219749221850/

In the articles that I’ve read while I was learning about proxy pattern, I saw 3 main types which are grouped by the use-case scenarios. So, I am going to mention about the proxy types so at the same time I am going to answer the most important question : When to use proxy pattern ?

1-)Remote Proxy :

Probably, we all used remote proxy pattern without even realizing. When we want to use a web service when you need to access to another network, we generally use proxy pattern. Also, in scenarios like when the client needs some specific responsibilities or authorities, not everything, proxy patterns helps us to use a smaller object and increases the responsibility. These all makes our app more SOLID (most of the time), faster and less complex, more scalable in general view.

2-)Virtual Proxy :

When it is too hard or expensive to reach the main resource, we use virtual proxy to manage access to creating an instance of the resource.

3-)Protection Proxy :

When we use a resource by using a proxy pattern to access a resource, we can create security protocols like authentications etc. and provide our app protection.

Attention : Protection Proxy Pattern may cause code complexity by adding one more layer between client and resource (real object / class).

To summarize, proxy pattern can be used for cross-cutting concerns, controlling access, logic, security. This pattern is also good for object duplications, some best practices of caching, maintain requests by filtering them.

Now, before our code implementation, I’ll explain 3 main components for proxy pattern which is going to help us to understand the concept and apply to our scenarios.

https://subscription.packtpub.com/book/application_development/9781785888038/5/ch05lvl1sec38/a-uml-class-diagram-for-the-proxy-pattern

Real Subject : As you can see, this is the resource class which our proxy is going to implement.

Subject: Class that both proxy and real classes are derived to use proxy on behalf of the real object more easily.

Proxy: This is our proxy class which will be used by client. This class is going to communicate with Real Subject and implement the responsibility, logic etc.

Here is the code example :

In our country, after a long long time we are finally allowed to go to restaurants and cafes so I am going to give actual a real time example :) Imagine you went to Starbucks and do the payment with your credit card. You don’t give all responsibility and authorization of your bank account to your credit card, but allow it to use the money in your account to do the payment.

So more technically, in this example IBankAccount is our subject class, BankAccount class which inherits the interface is our real object and BankAccountProxy class is going to be our proxy class which is an access point to real object (BankAccount class). And, in the Program.cs, in main method, we are going to call the related method via BankAccountProxy without communicating the real object’s itself — the bridge.

namespace ProxyPattern
{
public interface IBankAccount
{
//This is our interface that both real object and proxy classes are going to inherit.
//You can have anything you need from the resource in this interface but our main purpose is to understand the logic so I am not going
//to implement all the code but an example.
public decimal ShowUpdatedAccountBalance(int accountId);
}
public class PaymentTransaction
{
int _accountId;
decimal _price;
public PaymentTransaction(int accountId,decimal price)
{
_accountId = accountId;
_price = price;
}
public Decimal Price { get { return _price; } }
}
public class BankAccount : IBankAccount
{
//BankAccount Class is our real object, I mean the resource. We have all main responsibilities or aythorities here.
int _accountId = 0;
public BankAccount(int accountId)
{
_accountId = accountId;

//do the necessary operations here.Reach the PaymentTransaction and find out the price.
//PaymentTransaction codes are not necesarry here. So, I do not implement. The goal is to understand
//main logic and usage of proxy pattern.
}
public decimal ShowUpdatedAccountBalance(int accountId)
{
decimal accountBalance = 0;
decimal price = _price;
return accountBalance - price;
}
}
public class BankAccountProxy : IBankAccount
{
//As the name indicates, this is our Proxy class. Here is the access point.
//I reach the ShowUpdatedAccountBalance() that is in real object.
BankAccount realSubject = null;
int accountId = 0;
public BankAccountProxy(int accountId)
{
}
public decimal ShowUpdatedAccountBalance(int accountId)
{
realSubject = new BankAccount(accountId);
var result = realSubject.ShowUpdatedAccountBalance(accountId);
return result;
}
}
class Program
{
static void Main(string[] args)
{
//Client doesn't reach the resource aka real object (BankAccount)
//Client calls the proxy object (BankAccountProxy) and reaches the real object via proxy.
BankAccountProxy myProxy = new BankAccountProxy(0);
myProxy.ShowUpdatedAccountBalance(0);
}
}

FlyWeight Pattern

This pattern is used when we want to decrease the memory usage and increase the performance. The important point is : we can decrease the memory usage with fly weigh pattern if only if a lots of similar objects cause the more memory usage. As we all know, fundamental motto of design patterns is creating a solution to repetitive problems. Similar to this motto, we reject to reproduce almost same kinds of objects. Instead, we are creating a pool and use the objects from there.

Store the similar kind of objects, and if you can’t find any matching for request, then create a new one.

We need to know 2 main concepts for using and understanding Flyweight pattern.

Intrinsic data : Datas which are stateless and generally remains unchanged, if any change occurs it would be reflected among all of the objects that reference the flyweight.

Extrinsic data : Datas which are stateful and computed at runtime and it is held outside of a flyweight object.

I wanted to implement uml diagram, it is so effective and actually summarizes all about flyweight pattern.

https://www.pinterest.com/pin/123708320999692064/

As I mentioned above we are going to have flyweight objets. So, FlyWeight interface defines the members of these objects. (Does what an interface does for its objects)

ConcreteFlyWeight class inherits our interface as unsharedFlyWeight does. We can create instances of concrete flyweight classes that are not shared at all.

FlyWeighFactory is a class that involves references for flyweight objects. GetFlyWeight method decides if there is a similar object in the pool or if we have to create a new one. Both actions making in this class.

You can find a perfect code example about this pattern from here : https://exceptionnotfound.net/flyweight-pattern-in-csharp/

Facade Pattern

Since I have started to learn Design Patterns, Facade became my favorite immediately because it is even easier than Singleton pattern. I am sure you have used Facade pattern before without even realizing it. So, put the masks on !

https://www.123rf.com/photo_128884970_stock-illustration-fake-person-bad-tired-man-deceive-concept-businessman-wear-smile-mask-isolated-flat-cartoon-characte.html

I mean, literally put the masks on. Facade pattern is a structural pattern that is generally used when working with complex APIs, frameworks, libraries, classes etc.. Instead of working with these complex structures all the time, Facade pattern goes between and helps us to use only what we need. It simplifies the code for client. Also, if we don’t want client to reach all the structure of a API for example, we can cover and hide it with the help of Facade pattern.

Let me explain why & when do we need facade pattern and then give the related uml diagram.

Imagine you have an application that you need to use one of that complex structures for a certain process. This means, every time you need that process, you have to deal with these complex structures : creating new objects, creating new relations…. We all know that kind of operations cause serious performance issues, prevents clean coding (causing copy-paste) and repetitive code. That’s why we need facade pattern. We let facade go in between and talk to complex structures on behalf of us. It also helps loosing couples which makes our application more readable, scalable and easy to modify with new technologies (this is also very important these days, recommend you to take a look into the companies that are in revolution from old architectures to service oriented architectures or even to micro services . They suffer because of the expensive costs : money, time, people and effort.)

http://gyanendushekhar.com/2016/08/21/facade-design-pattern-c/

Note that, the classes that are in sub-systems works independently from each other and also from facade.

So, it’s your choice if you want to make the functionalities that are in the sub-classes private in case of preventing them to be reached from client instead of with facade.

See the example for the facade pattern with code below :

I have separate teams : Developers, POs, Testers and Analysts. I want to create a whole Software Product Team that includes these all teams with different numbers of people and there are other parameters. What I want to say is, I want these teams to continue working separately, don’t loose any functionalities but also contribute to united team I am going to create. So, I am going to create a Facade and my client side is going to be able to use what needed from these objects but not more. Thus, the teams are going to continue to work independently.

namespace FacadePattern
{
public class Analysts
{
public string Name { get; set; }
public double Age { get; set; }
public int ExperienceOfYears { get; set; }
public List<string > Tools { get; set; }
}
public class Developers
{
public string Name { get; set; }
public double Age { get; set; }
public int ExperienceOfYears { get; set; }
public string Framework { get; set; }
public List<string> Techs { get; set; }
}
public class ProjectOwners
{
public string Name { get; set; }
public double Age { get; set; }
public int ExperienceOfYears { get; set; }
public List<string> Languages { get; set; }
public List<string> Certificates { get; set; }
}
public class Testers
{
public string Name { get; set; }
public double Age { get; set; }
public int ExperienceOfYears { get; set; }
public bool WriteTestCode { get; set; }
public List<string> Techs { get; set; }
public List<string> Tools { get; set; }
public bool UseSql { get; set; }
}
public class TheTeam
{
public TheTeam CreateMyteam(int numberOfDevs, int numberOfAnalysts, int numberOfTesters, int numberOfPOS)
{
TheTeam myTeam = new TheTeam();
return myTeam;
}
}
public class TeamCreator
{
public Developers Developers { get; set; }
public Analysts Analysts { get; set; }
public Testers Testers { get; set; }
public ProjectOwners ProjectOwners { get; set; }
public TeamCreator(Developers DeveloperTeam, Analysts AnalystTeam,Testers TestTeam,ProjectOwners ProjectOwnersTeam)
{
this.Developers = DeveloperTeam;
this.Analysts = AnalystTeam;
this.Testers = Testers;
this.ProjectOwners = ProjectOwnersTeam;
}
public TheTeam CreateTheTeam(int numberOfDevs, int numberOfAnalysts,int numberOfTesters,int numberOfPOS)
{
TheTeam creator = new TheTeam();
return creator.CreateMyteam(5, 3, 4, 1);
}
}
class Program
{
static void Main()
{
TeamFacade facade = new TeamFacade();
facade.UniteTheTeam();
}
}
}

Bridge Pattern

The bridge pattern is a design pattern used in software engineering that is meant to “decouple an abstraction from its implementation so that the two can vary independently”, introduced by the Gang of Four.

Key words are here : Divide and delegate.

When there are multiple types of implementation of a function or multiple types of usage of this implementation, bridge pattern is used for separating abstraction from its implementation and make them to be developed independently. What to consider here is : implementations of course should have a common interface. So that, the client can be able to use abstraction without worrying about the implementation. This pattern makes difference specially when there are huge classes and a lot of way of implementations.

To summarize before the code example, our claim is to create a structure that implementations and abstractions / interfaces are separate and independent. Client is able to use interface / abstraction without thinking about the implemenatation.

While studying, I immediately remembered about Abstract Factory Pattern (close to home). I started to research what is the difference between Abstract factory Pattern and Bridge Pattern ?

https://www.codeproject.com/Articles/29729/Most-Commonly-Used-dEsign-pAttern

One of the most popular answer is : One is creational design pattern one is structural .(ı want to believe you also didn’t satisfied with this answer like me !). When I read 1–2 blog posts and go back to my abstract factory pattern code implementation examples I reached the point : What ı repeated about bridge pattern is abstraction and implementation should be independent. They can be developed separately and client don’t have to think about anything but the abstraction. But in abstract factory pattern it’s not that way. I mean, if you change the abstraction you have to change the other dependent ones as well. But in bridge pattern, components are independent.

Of course, again I am going to code an example about cars :). In the example below, we have an application that manufactures diesel or gasoline powered cars. After that we specify if the car is Manuel or automatic. For example a diesel-automatic car and Manuel-gasoline powered car : they are both cars but have different FuelTypes : abstraction has just appeared. Now, we can create an abstraction named IFuelTypes. After doing the needed steps, we have 2 independent structures and they both can be expanded separately.

namespace BridgePattern
{
public class Car
{
public IFuelType FuelType { get; set; }
public Car(IFuelType fuelType)
{
FuelType = fuelType;
}
public virtual void Complete()
{
FuelType.Manufacture();
}
}
public interface IFuelType
{
void Manufacture();
}
public class DieselFuelType : IFuelType
{
public void Manufacture()
{
Console.WriteLine("Fuel type is diesel.");
}
}
public class GasolineFuelType : IFuelType
{
public void Manufacture()
{
Console.WriteLine("Fuel Type is Gasoline.");
}
}
public class ManuelCar : Car
{
public ManuelCar(IFuelType fuelType) : base(fuelType)
{
}
public override void Complete()
{
Console.WriteLine("Manuel Car is Ready !");
base.Complete();
}
}
public class AutomaticCar : Car
{
public AutomaticCar(IFuelType fuelType) : base(fuelType)
{
}
public override void Complete()
{
Console.WriteLine("Automatic car is Ready !");
base.Complete();
}
}
class Program
{
static void Main()
{
Car car = new ManuelCar(new DieselFuelType());
car.Complete();
Car newCar = new AutomaticCar(new GasolineFuelType());
newCar.Complete();
}
}

Decorator Pattern

Decorative pattern is basically sub-classing for extending functionality. Wrap the objects and modify with respect to your needs. We do not change the object’s definition. Original objects and decorators follow the same interface. So, at the end of the final object is going to be a composition of original object and decorator.

Let me explain with help of a diagram in simplest way possible : ((Please don’t judge me, I am literally bad at this kind of drawing things :))

I have a base : CAR. There are different kind of cars, in this example diesel, automatic and highline -> sub-classing has just started. I want to extend the structure and create a diesel automatic car, one step further : a car that is diesel automatic highline. As you see, the base is the same for all of them. So, the my final car type includes all behaviors of them. Inheritance or modifying the existing classes are just gonna be waste of time and sometimes not even possible without refactoring or changing the whole classes sometimes. Because we already have the things, all we need to is just extending them.

As you see up on the diagram, we have an existing class and we want to add new functionalities, or at least modify. Inheritance is usually a solution, but there are scenarios that it won’t work or not efficiently work :

-I derive a new class for my purpose. And imagine I need 2 or n of the functions which are in these existing classes. In real scenarios things never go as planned or expected so 90% probably, inheritance is gonna be either too hard & complex to code, handle and implement. Or even in the best scenario performance issues will appear. Because with this kind of solution you ignore SOLID’s O principle. And of course, as a developer you always have to think about the next person that is going to use your code and does the same things for n times. This is not welcomed ! So in scenarios like this, just wrap your object with a decorator and add other functionalists at run time. The decorator is going to look like the original class. And also we don’t modify the original class.

You can see the code example below :

namespace DecoratorPattern
{
public interface ICar
{
//public string Model { get; set; }
decimal CalculatePrice();
string GetInformation();
}
public class DieselCar : ICar
{
public decimal CalculatePrice()
{
return 1;
}
public string GetInformation()
{
return "";
}
}
public class AutomaticCar : ICar
{
public decimal CalculatePrice()
{
return 1;
}
public string GetInformation()
{
return "";
}
}
public class HighlineCar : ICar
{
public decimal CalculatePrice()
{
return 1;
}
public string GetInformation()
{
return "";
}
}
public abstract class CarDecoratorPattern : ICar
{
private ICar car;
public CarDecoratorPattern(ICar _car)
{
this.car = _car;
}
public virtual decimal CalculatePrice()
{
return this.car.CalculatePrice();
}
public virtual string GetInformation()
{
return this.car.GetInformation();
}
}
public class Package1 : CarDecoratorPattern
{
public Package1(ICar _car) : base(_car)
{
}
public override decimal CalculatePrice()
{
return base.CalculatePrice();
}
public override string GetInformation()
{
return base.GetInformation();
}
}
public class Package2 : CarDecoratorPattern
{
public Package2(ICar _car) : base(_car)
{
}
//Do not forget adding virtual keyword in decorator to not to get any erros here, overriding the function.
public override decimal CalculatePrice()
{
return base.CalculatePrice();
}
public override string GetInformation()
{
return base.GetInformation();
}
}
}
class Program
{
static void Main(string[] args)
{
ICar car = new DieselCar();
CarDecoratorPattern carDecorator = new Package1(car);
carDecorator = new Package2(carDecorator);
Console.WriteLine("Car's Price : " + carDecorator.CalculatePrice());
Console.WriteLine("Car's Information : " + carDecorator.GetInformation());
}
}

Hope you enjoyed the post. Any feedback is welcomed, thank you for reading !

--

--