If you are new, I highly recommend you to read my first article which is about Creational Design Patterns In C#. As we explained in an earlier post, we have three main categories in Design Patterns,
- Creational
- Structural
- Behavioral
Structural Design Patterns help you to put types and objects and other stuff together to create a bigger struct but at the same time, it keeps high flexibility and optimum performance for you. There are seven patterns that exists in this family,
- Adapter
- Bridge
- Composite
- Decorator
- Facade
- Flyweight
- Proxy
Adapter Design Pattern
As its name implies, the adapter pattern adjusts communication between two alien types and make them understand each other.
public class AlienType {
public string SayJupiterianHi() {
return "Hello Man from Earth, I am from JUPITER";
}
}
public interface IAdapter {
string SayHi();
}
public class Adapter: IAdapter {
private readonly AlienType _alienType;
public Adapter(AlienType alienType) {
_alienType = alienType;
}
public string SayHi() {
return _alienType.SayJupiterianHi();
}
}
public static class AdapterExample {
public static void Test() {
var adapter = new Adapter(new AlienType());
Console.WriteLine(adapter.SayHi());
}
//result:
//Hello Man from Earth, I am from JUPITER
}
Bridge Design Pattern
This pattern separates interface or abstraction from its implementation, so for example you may be using two different technologies in two implementations.
public interface IBridge {
void PrintDetails();
}
public class BridgeA: IBridge {
public void PrintDetails() {
Console.WriteLine("data across Bridge A");
}
}
public class BridgeB: IBridge {
public void PrintDetails() {
Console.WriteLine("data across Bridge B");
}
}
public interface IBridgeUser {
public IBridge Bridge {
get;
set;
}
void PrintDetails();
}
public class BridgeUser: IBridgeUser {
public IBridge Bridge {
get;
set;
}
public void PrintDetails() {
Bridge.PrintDetails();
}
}
public static class BridgeExample {
public static void Test() {
var bridgeUser = new BridgeUser();
bridgeUser.Bridge = new BridgeA();
bridgeUser.PrintDetails();
bridgeUser.Bridge = new BridgeB();
bridgeUser.PrintDetails();
}
//result:
//data across Bridge A
//data across Bridge B
}
Composite Design Pattern
In simple words, we put objects in one bigger object with a tree structure so we can present hierarchies, and also this pattern let you treat uniformly with a single object or composite object.
public abstract class Animal {
protected string Name;
protected Animal(string name) {
Name = name;
}
public virtual void Add(Animal animal) {
throw new NotImplementedException();
}
public virtual void PrintTree(int indent) {
throw new NotImplementedException();
}
}
public class Species: Animal {
public Species(string name): base(name) {}
public override void PrintTree(int indent) {
Console.WriteLine(new String('-', indent) + " " + Name);
}
}
public class SpeciesComposite: Animal {
private readonly List < Animal > _animals = new List < Animal > ();
public SpeciesComposite(string name): base(name) {}
public override void Add(Animal animal) {
_animals.Add(animal);
}
public override void PrintTree(int indent) {
Console.WriteLine(new String('-', indent) + "+ " + Name);
// Display each child element on this node
foreach(var animal in _animals) {
animal.PrintTree(indent + 2);
}
}
}
public static class CompositeExample {
public static void Test() {
var mammal = new SpeciesComposite("Mammal");
var carnivore = new SpeciesComposite("Carnivore");
var nonCarnivore = new SpeciesComposite("Non-Carnivore");
var tiger = new Species("Tiger");
var leopard = new Species("Leopard");
var sheep = new Species("Sheep");
var cow = new Species("Cow");
carnivore.Add(tiger);
carnivore.Add(leopard);
nonCarnivore.Add(sheep);
nonCarnivore.Add(cow);
mammal.Add(carnivore);
mammal.Add(nonCarnivore);
mammal.PrintTree(1);
}
//result:
//-+ Mammal
//---+ Carnivore
//----- Tiger
//----- Leopard
//---+ Non-Carnivore
//----- Sheep
//----- Cow
}

Join the conversation! Your thoughts help the community grow.