Structural Design pattern — [Notes]
· Structural Design pattern
· Adapter design pattern
∘ When?
· Flyweight design pattern
∘ Types of Entities
∘ Applying flyweight pattern
· Flyweight vs Prototype
· Decorator Pattern
Structural Design pattern
How are classes structured internally
Memory optimization wrt structure
Handling complex scenario in classes
How are classes going to interact with other classes
Adapter design pattern
We use an adapter to provide an uniform interface to a diverse set of external entities
When?
- We connect with third party APIs, SDKs, packages
- We might want to change the APIs in future [Some other API provider]
- If I have to do lot of change in my internal codebase. [PhonePe to Yesbank may need to be changed to some other bank]
If you have to connect to an external System (API, package), Build a uniform way in which you can connect to those system.
Examples -
Flyweight design pattern
Flyweight is a structural design pattern that lets you fit more objects into the available amount of RAM by sharing common parts of state between multiple objects instead of keeping all of the data in each object. [Source]
public class Bullet {
float Caliber,
int damange,
float cur_speed,
int user_id,
enum direction,
float[] position,
int weight,
jImage/Skin
}
Types of Entities
- Intrinsic Entities — Entities whose value will remain the same across every instance
- Extrinsic Entities — Entities whose value will keep on change.
public class Bullet {
float Caliber, //Intrinsic
int damange, //extrinsic
float cur_speed, //extrinsic
int user_id, //extrinsic
enum direction, //extrinsic
float[] position, //extrinsic
int weight, //Intrinsic
jImage/Skin //Intrinsic
}
Applying flyweight pattern
//All intrintic properties
Bullet{
Caliber,
Weight,
Image
}
//All extrintic properties
//Immutable
FlyingBullet {
damage,
cur_speed,
owner,
direction
}
//Complete bullet - Intrinsic + extrintic properties
Flying Bullet {
damage,
cur_speed,
owner,
direction
Bullet bullet //all intrinsic properties refer to same object
}
Flyweight vs Prototype
Prototype
- Only 1 class
- we’ll fill some fields in advance
- n prototype the common properties need not be immutable
Flyweight
- 2 classes
- 1(one) class will be immutable
- save memory
Decorator Pattern / Wrapper pattern
Decorator is a structural design pattern that lets you attach new behaviors to objects by placing these objects inside special wrapper objects that contain the behaviors. Source
Decorator pattern is useful when you want to add new functionalities or responsibilities to individual objects without changing the structure or behaviour of the object
- Mix and match different options instead of having different class implementation
- Single responsibility
- We have a type of object. We might want to add things to it (decorate the object with some things)
Pizza final = Mushroom(Oregano(Cheese(Paneer(Pizza))))
final.order() => total cost and list of items in the pizza
- decorator class is always a abstract class
- has a paramteterized constructor that takes the base class as input
public interface Pizza {
getTotalCost();
getItems();
}
class Paneer extends Pizza {
Pizza p;
Paneer(Pizza pizza){
this.p = pizza
}
@Override
public int getTotalCost(){
return this.p.getTotalCost()+paneer_cost;
}
getItems(){
return p.getItems() + "Paneer";
}
}
class Cheese extends Pizza {
Pizza p;
Cheese(Pizza pizza){
this.p = pizza
}
@Override
public int getTotalCost(){
return this.p.getTotalCost()+cheese_cost;
}
getItems(){
return p.getItems() + "Cheese";
}
}
Real life examples of decorator pattern
Trivial example (Flat version) —
With Decorator pattern