Abstract Factory Pattern: One Order, One Matching Thali
Understand the Abstract Factory design pattern through an Indian wedding catering story, with simple TypeScript and Python code, diagrams, and practice.
๐ฏ The story of Meena Tai's wedding catering
Let us begin with a busy wedding morning in Nashik.
Meena Tai runs Swaad Caterers. Families book her for weddings, and she offers complete meal styles. A customer can choose a Gujarati thali or a South Indian thali. Whichever style is chosen, every guest's plate gets three things: a starter, a main course, and a sweet.
Here is the important rule of her kitchen: everything on one plate must belong to the same style. If the family books a Gujarati thali, the plate gets dhokla, then thepla with shaak, and shrikhand at the end. If they book South Indian, the plate gets medu vada, then dosa with sambar, and payasam to finish.
Now imagine a disaster. It is the Shah family wedding. Five hundred guests. Meena Tai's newest helper, a nervous young man named Bunty, is running between counters with plates. In the rush, Bunty puts payasam on a Gujarati plate. The grandmother of the bride โ everyone calls her Dadi ji โ notices in two seconds flat. "Beta, this sweet does not match the thali!" Bunty turns red. The mistake is small, but in catering, matching matters. The whole set must belong together.
That night, Meena Tai cannot sleep. She thinks: the problem is not Bunty. The problem is that my kitchen allows mixing. So she makes a smart system. She does not let helpers pick dishes one by one from open trays. Instead, each wedding gets one counter โ either the Gujarati counter or the South Indian counter. A helper simply goes to the counter and asks: "one starter, please", "one main, please", "one sweet, please". The helper never names the dish. The counter guarantees that everything it hands out belongs to one matching style.
Choose the counter once, and a thousand plates come out perfectly matched. It becomes impossible to mix styles, because only one counter is in the room. Even Bunty cannot make the payasam mistake now โ there is simply no payasam at the Gujarati counter.
The counter is a factory that produces a whole family of matching products. That is exactly the Abstract Factory pattern. Keep this catering story with you โ Meena Tai, Bunty, and Dadi ji will walk with us through every section, and we will write their kitchen in code soon.
๐ก What is the Abstract Factory pattern?
Abstract Factory is a creational design pattern. Its job: create families of related objects without naming their concrete classes in your main code.
Let us unpack that slowly, with the kitchen in front of us:
- A product kind is a role on the plate: starter, main course, sweet.
- A family (also called a variant) is a style: Gujarati or South Indian.
- The abstract factory is an interface that says: "Any counter must be able to give a starter, a main, and a sweet." It promises what can be made, not which version.
- A concrete factory implements that interface for one family. The Gujarati counter gives dhokla, thepla-shaak, and shrikhand. The South Indian counter gives medu vada, dosa-sambar, and payasam.
Your main code (the client โ that is Bunty) holds a reference to the abstract factory only. It asks for "a starter" and trusts the answer. It never writes new Dhokla() anywhere.
This pattern also comes from the Gang of Four book (1994), where it is sometimes called a Kit or Toolkit, because the factory hands you a complete kit of matching parts.
One-line summary: Abstract Factory = choose the family once, and one factory object gives you every matching member of that family. In kitchen language: pick the counter once, and every plate matches.
Compare with the Factory Method pattern you learned earlier: Sharma Aunty's branches created one product (the vehicle) through one overridable method. Meena Tai's counters create a whole set of products that must fit together. The emphasis is on the word family.
College corner: in GoF terms, Abstract Factory raises the level of abstraction one step above Factory Method. Factory Method varies one object via inheritance (subclass overrides a method). Abstract Factory varies a coherent set via object composition (the client is configured with a factory object). The matching guarantee is enforced by the type system: a GujaratiThaliFactory has no member that can return a South Indian product, so cross-family invariants hold statically, not by runtime discipline.
โ ๏ธ The problem it solves
Let us feel the pain first. Suppose Meena Tai's nephew codes Swaad Caterers without the pattern. Every dish decision becomes an if-else on the style:
// BAD CODE: style checks scattered through the kitchen
function serveGuestPlate(style: string): void {
// starter
if (style === "gujarati") {
console.log("Serving dhokla");
} else {
console.log("Serving medu vada");
}
// main course
if (style === "gujarati") {
console.log("Serving thepla with shaak");
} else {
console.log("Serving dosa with sambar");
}
// sweet
if (style === "gujarati") {
console.log("Serving shrikhand");
} else {
console.log("Serving payasam");
}
}This already looks repetitive with two styles and three dishes. Now scale it like real life:
- A new family arrives. Meena Tai adds a Punjabi thali for a Chandigarh family. We must hunt down every
if-elsein the whole codebase and add a branch. Miss one spot, and a Punjabi wedding gets shrikhand by accident โ exactly the mixed-plate disaster from our story, but now hidden in code. - Nothing enforces matching. The compiler is perfectly happy if one function serves a Gujarati starter and another serves a South Indian sweet to the same guest. The bug appears only at the wedding, at runtime, in front of Dadi ji.
- Creation logic pollutes business logic. Code that should be about serving guests is crowded with which dish belongs to which style decisions, repeated everywhere.
And where does the pain actually land when this code grows? Mostly in two places: hunting style checks during every change, and firefighting mixed-family bugs that only appear at runtime.
What we really want is one decision point: choose the style once at booking time, and after that, every dish created automatically belongs to the correct, mutually matching family. That is the promise of Abstract Factory โ Meena Tai's one-counter rule, written in types.
๐ ๏ธ How Abstract Factory works, step by step
Let us build the solution slowly. There is a neat trick for planning: draw a matrix (a table) first. Meena Tai actually has this matrix painted on her kitchen wall:
| Gujarati family | South Indian family | |
|---|---|---|
| Starter | Dhokla | Medu Vada |
| Main course | Thepla with Shaak | Dosa with Sambar |
| Sweet | Shrikhand | Payasam |
The rows are product kinds. The columns are families. Every cell is one concrete class. Now follow these steps:
- One interface per row. Create abstract products:
Starter,MainCourse,Sweet. Every dish in that row implements its row's interface. - One abstract factory with one method per row. Create
ThaliFactorywithcreateStarter(),createMainCourse(),createSweet(). Each method returns the abstract product type. - One concrete factory per column.
GujaratiThaliFactoryreturns the Gujarati cells;SouthIndianThaliFactoryreturns the South Indian cells. Each concrete factory produces dishes from exactly one column โ that is how matching is guaranteed. - Write the client against abstractions only. The serving code receives a
ThaliFactory(usually through its constructor) and works only withStarter,MainCourse, andSweetreferences. Bunty only knows roles, never dish names. - Select the concrete factory once. At booking time (the program's start), read the customer's choice and create the matching factory. Pass it down. Nothing downstream ever learns which family it is using.
(The MainCourse row is left out of the diagram only to keep it readable โ it follows the exact same shape.)
Notice the guarantee: a GujaratiThaliFactory object simply has no code path that can produce payasam. Mixing families stops being a discipline problem and becomes structurally impossible. The type system does the policing, so Bunty can relax.
Here is one guest being served, as a conversation in time. Bunty (the client) talks only to the counter, and the counter answers with matching dishes:
College corner: each individual method on the factory (createStarter()) is itself a Factory Method. Abstract Factory is therefore best understood as a bundle of Factory Methods grouped under one invariant: "all of my outputs belong to one variant." When you see a class whose only job is a coherent set of createX() methods, you are looking at this pattern even if nobody named it.
๐งช Real-life code example
Now let us write Swaad Caterers fully in TypeScript. We will go section by section, exactly mirroring the wall matrix.
Section 1: the abstract products. One interface per row of our matrix.
// ---------- ABSTRACT PRODUCTS (the rows) ----------
interface Starter {
name: string;
serve(): void;
}
interface MainCourse {
name: string;
serve(): void;
}
interface Sweet {
name: string;
serve(): void;
}Section 2: the concrete products. Every cell of the matrix becomes a small class.
// ---------- GUJARATI FAMILY ----------
class Dhokla implements Starter {
name = "dhokla";
serve(): void {
console.log(" Starter: soft dhokla with green chutney.");
}
}
class TheplaShaak implements MainCourse {
name = "thepla with shaak";
serve(): void {
console.log(" Main: thepla with bateta nu shaak.");
}
}
class Shrikhand implements Sweet {
name = "shrikhand";
serve(): void {
console.log(" Sweet: chilled kesar shrikhand.");
}
}
// ---------- SOUTH INDIAN FAMILY ----------
class MeduVada implements Starter {
name = "medu vada";
serve(): void {
console.log(" Starter: crispy medu vada with coconut chutney.");
}
}
class DosaSambar implements MainCourse {
name = "dosa with sambar";
serve(): void {
console.log(" Main: paper dosa with hot sambar.");
}
}
class Payasam implements Sweet {
name = "payasam";
serve(): void {
console.log(" Sweet: warm semiya payasam.");
}
}Section 3: the abstract factory and the concrete factories. This is the heart of the pattern โ the counters from our story.
// ---------- ABSTRACT FACTORY ----------
// "Any counter must be able to give these three things."
interface ThaliFactory {
styleName: string;
createStarter(): Starter;
createMainCourse(): MainCourse;
createSweet(): Sweet;
}
// ---------- CONCRETE FACTORIES (the columns) ----------
class GujaratiThaliFactory implements ThaliFactory {
styleName = "Gujarati";
createStarter(): Starter {
return new Dhokla();
}
createMainCourse(): MainCourse {
return new TheplaShaak();
}
createSweet(): Sweet {
return new Shrikhand();
}
}
class SouthIndianThaliFactory implements ThaliFactory {
styleName = "South Indian";
createStarter(): Starter {
return new MeduVada();
}
createMainCourse(): MainCourse {
return new DosaSambar();
}
createSweet(): Sweet {
return new Payasam();
}
}Read GujaratiThaliFactory again slowly. Every method returns a dish from the same column. There is no way for this class to hand out payasam. That is the matching guarantee, written in plain code. Dadi ji could read this class and smile.
Section 4: the client. The serving crew works only with abstractions.
// ---------- CLIENT ----------
class WeddingService {
// The factory comes in through the constructor.
// The crew never knows WHICH concrete factory it is.
constructor(private factory: ThaliFactory) {}
serveGuest(guestName: string): void {
console.log(`Plate for ${guestName} (${this.factory.styleName} thali):`);
const starter = this.factory.createStarter();
const main = this.factory.createMainCourse();
const sweet = this.factory.createSweet();
starter.serve();
main.serve();
sweet.serve();
}
}Look how clean serveGuest is. No if. No style strings. No dish names. Only roles: starter, main, sweet. This is Bunty after the new system โ calm, fast, and unable to make the payasam mistake.
Section 5: the booking desk โ the single decision point.
// ---------- COMPOSITION ROOT ----------
// The ONLY place that knows concrete factories.
function bookWedding(style: "gujarati" | "south-indian"): WeddingService {
const factory: ThaliFactory =
style === "gujarati"
? new GujaratiThaliFactory()
: new SouthIndianThaliFactory();
return new WeddingService(factory);
}
const shahWedding = bookWedding("gujarati");
shahWedding.serveGuest("Dadi ji");
shahWedding.serveGuest("Rohan");
const iyerWedding = bookWedding("south-indian");
iyerWedding.serveGuest("Paati");Running this prints:
Plate for Dadi ji (Gujarati thali):
Starter: soft dhokla with green chutney.
Main: thepla with bateta nu shaak.
Sweet: chilled kesar shrikhand.
Plate for Rohan (Gujarati thali):
Starter: soft dhokla with green chutney.
Main: thepla with bateta nu shaak.
Sweet: chilled kesar shrikhand.
Plate for Paati (South Indian thali):
Starter: crispy medu vada with coconut chutney.
Main: paper dosa with hot sambar.
Sweet: warm semiya payasam.Every plate is perfectly matched. Dadi ji is happy. Bunty gets a raise.
Now the magic moment: Meena Tai launches the Punjabi thali. What changes in the old code? Nothing. We only add one new column:
class PaneerTikka implements Starter {
name = "paneer tikka";
serve(): void {
console.log(" Starter: smoky paneer tikka.");
}
}
class CholeBhature implements MainCourse {
name = "chole bhature";
serve(): void {
console.log(" Main: chole with fluffy bhature.");
}
}
class GajarHalwa implements Sweet {
name = "gajar halwa";
serve(): void {
console.log(" Sweet: hot gajar ka halwa with ghee.");
}
}
class PunjabiThaliFactory implements ThaliFactory {
styleName = "Punjabi";
createStarter(): Starter {
return new PaneerTikka();
}
createMainCourse(): MainCourse {
return new CholeBhature();
}
createSweet(): Sweet {
return new GajarHalwa();
}
}WeddingService does not change by even one character. Only the booking desk gets one more option. This is the Open/Closed Principle again: new family = new code, not edited code.
๐ The same idea in Python
The pattern is not tied to one language. Here is a compact Python version of the same kitchen:
from abc import ABC, abstractmethod
# ----- abstract products -----
class Starter(ABC):
@abstractmethod
def serve(self) -> None: ...
class Sweet(ABC):
@abstractmethod
def serve(self) -> None: ...
# ----- concrete products -----
class Dhokla(Starter):
def serve(self) -> None:
print(" Starter: dhokla")
class MeduVada(Starter):
def serve(self) -> None:
print(" Starter: medu vada")
class Shrikhand(Sweet):
def serve(self) -> None:
print(" Sweet: shrikhand")
class Payasam(Sweet):
def serve(self) -> None:
print(" Sweet: payasam")
# ----- abstract factory -----
class ThaliFactory(ABC):
@abstractmethod
def create_starter(self) -> Starter: ...
@abstractmethod
def create_sweet(self) -> Sweet: ...
# ----- concrete factories -----
class GujaratiThaliFactory(ThaliFactory):
def create_starter(self) -> Starter:
return Dhokla()
def create_sweet(self) -> Sweet:
return Shrikhand()
class SouthIndianThaliFactory(ThaliFactory):
def create_starter(self) -> Starter:
return MeduVada()
def create_sweet(self) -> Sweet:
return Payasam()
# ----- client -----
def serve_guest(factory: ThaliFactory) -> None:
factory.create_starter().serve()
factory.create_sweet().serve()
serve_guest(GujaratiThaliFactory()) # dhokla + shrikhand, always matched
serve_guest(SouthIndianThaliFactory()) # medu vada + payasam, always matchedSame shape, different language: interfaces for rows, one factory class per column, a client that only sees abstractions.
And one small C# variation that real teams love โ the testing family. In production, the app receives the real factory; in tests, it receives a fake factory whose whole family is made of harmless fakes:
public interface IKitchenFactory
{
IOven CreateOven();
IBillPrinter CreatePrinter();
}
// Production column: real machines.
public class RealKitchenFactory : IKitchenFactory
{
public IOven CreateOven() => new GasOven();
public IBillPrinter CreatePrinter() => new ThermalPrinter();
}
// Test column: everything fake, everything safe.
public class FakeKitchenFactory : IKitchenFactory
{
public IOven CreateOven() => new RecordingFakeOven();
public IBillPrinter CreatePrinter() => new InMemoryPrinter();
}
// The client never knows which world it lives in:
var kitchen = new KitchenService(new FakeKitchenFactory());Swap one factory, and you swap the entire world the client lives in โ real or fake, but always internally consistent. That is the family guarantee doing double duty as a testing tool.
๐ก Where you see it in real software
Abstract Factory quietly powers a lot of famous software:
- Java's
DocumentBuilderFactory.newInstance()in thejavax.xml.parserspackage is a textbook example. You ask the abstract factory for aDocumentBuilder, and it returns the right concrete XML-parsing family for your environment โ your code never names the parser implementation. Its siblingTransformerFactory.newInstance()works the same way. - .NET's
DbProviderFactory(inSystem.Data.Common) is a beautiful family factory. One factory object gives youCreateConnection(),CreateCommand(), andCreateDataAdapter()โ and all of them belong to the same database family (all SQL Server pieces, or all MySQL pieces). It would be a disaster to pair a SQL Server connection with a MySQL command; the factory makes that impossible, exactly like our thali counter. - Cross-platform UI toolkits use the pattern for look-and-feel: choose the platform family once, and every widget created afterwards โ button, checkbox, scrollbar โ automatically matches that platform's style. This was the original motivating example in the GoF book.
- Test code vs production code. Many apps pass a "real services" factory in production and a "fake services" factory in tests, as in our C# snippet above. Same client code, two consistent families.
For deeper study, see the worked examples in iluwatar/java-design-patterns (a kingdom example with elf and orc families), the short Python version in faif/python-patterns, and the illustrated guide on Refactoring Guru.
๐ฏ When to use it and when not to
First, find your project on this map. Swaad Caterers sits high and right: several product kinds that must match, and new families keep arriving.
Then confirm with the table:
| Situation | Use Abstract Factory? | Why |
|---|---|---|
| You have several products that must be used together as a matching set | โ Yes | The factory makes mixing families impossible |
| You expect new families (new themes, new platforms, new menu styles) | โ Yes | A new family is just one new factory class plus its products |
| You want all concrete-class knowledge in one startup spot | โ Yes | Only the composition root names concrete factories |
| You need real vs fake object sets for testing | โ Yes | Swap one factory, swap the whole world |
| You have only one product kind | โ No | A single Factory Method is enough โ no family exists |
| Product kinds change often (new rows in the matrix) | โ No | Every new kind forces edits in all concrete factories |
| The program is small and variants will never appear | โ No | The extra interfaces and classes are pure overhead |
That second โ row deserves attention. Remember the wall matrix: the pattern loves new columns (families) but hates new rows (product kinds). The chart below shows both directions for our kitchen with three families on board:
Adding the Punjabi family with the pattern touched one existing file (the booking desk). But adding a createDrink() row forces Gujarati, South Indian, and Punjabi factories โ plus the interface โ to all change at once. Plan your rows carefully at the start, the way Meena Tai planned her wall matrix before painting it.
College corner: this asymmetry is a classic instance of the expression problem: class hierarchies make it easy to add new variants but hard to add new operations, while functional sum types do the opposite. Abstract Factory deliberately optimizes the variant axis. If your domain grows along the kind axis instead, consider visitor-style designs, or accept periodic interface churn with default implementations to soften the blow.
๐ ๏ธ Lifecycle of one wedding booking
Watch where the big decision happens: exactly once, at booking. After the FactoryChosen state, the kitchen never asks "which style?" again โ it just serves.
The self-loop on ServingGuests is the beauty of the pattern: hundreds of creations happen there, and not one of them re-asks the family question. Compare this with the no-pattern flowchart in Figure 3, where every single plate re-asked it three times.
๐ Compare with cousins
| Pattern | Creates | Strength | Watch out for |
|---|---|---|---|
| Abstract Factory | A family of related products | Guarantees the set matches | New product kinds are costly |
| Factory Method | One product | Simple; great starting point | One method, one product only |
| Builder | One complex product, step by step | Readable assembly of big objects | Not about families at all |
| Prototype | A copy of an existing object | No subclassing needed | Needs a good clone operation |
| Singleton | One single shared instance | Often used for the concrete factory | Different purpose entirely |
A few useful relationships to remember, in story language:
- Each method inside an Abstract Factory (
createStarter(),createSweet()) is usually implemented as a Factory Method. So Meena Tai's counter is really a team of Sharma Aunty's tricks working together. - Designs often start with one Factory Method and grow into an Abstract Factory when more related products appear. Aunty's tiffin shop could one day become a catering counter.
- A concrete factory is often made a Singleton, because one Gujarati counter is enough for the whole wedding.
- Builder answers a different question: not "which family?" but "how do I assemble this one complicated object?" An Abstract Factory can even return ready-made builders โ a counter that hands you order slips.
โ ๏ธ Common mistakes students make
Mistake 1: Asking two different factories for one plate. If the client creates new GujaratiThaliFactory() in one function and new SouthIndianThaliFactory() in another, you have re-created Bunty's payasam disaster with extra steps. The factory must be chosen once and passed down โ usually through a constructor.
Mistake 2: Returning concrete types from the factory methods. If createStarter() declares its return type as Dhokla instead of Starter, client code starts depending on the concrete class and the decoupling evaporates. Factory methods must return the abstract product type.
Mistake 3: Confusing it with Factory Method. "I have a factory class, so it must be Abstract Factory" โ not necessarily! If it creates just one product, it is a Factory Method (or a simple factory). The word abstract here refers to a factory interface with multiple creation methods producing a family.
Mistake 4: Designing the matrix lazily. Students often start with one product kind, then keep bolting on createX() methods every week. Each addition breaks every concrete factory. Sit down first, list your rows (kinds) and columns (families), and only then write the interfaces โ paint the wall matrix before opening the kitchen.
The same list as a quick-scan table:
| Mistake | What it looks like | The fix |
|---|---|---|
| Two factories for one plate | Different new XFactory() calls in different functions | Choose once at the composition root, pass it down |
| Concrete return types | createStarter(): Dhokla | Always return the abstract product type |
| Wrong pattern name | Calling any factory class an Abstract Factory | Family of methods = Abstract Factory; one method = Factory Method |
| Lazy matrix | New createX() bolted on weekly | Plan rows and columns before writing interfaces |
๐งช Quick revision box
+=================================================================+
| ABSTRACT FACTORY - QUICK REVISION |
+=================================================================+
| IDEA : One factory interface creates a whole FAMILY |
| of matching products. Pick the family once. |
| ALSO CALLED: Kit / Toolkit (GoF, 1994) |
|-----------------------------------------------------------------|
| THE MATRIX |
| rows = product kinds (Starter, Main, Sweet) |
| columns = families (Gujarati, South Indian, Punjabi) |
| one interface per ROW, one concrete factory per COLUMN |
|-----------------------------------------------------------------|
| GOLDEN RULES |
| 1. Client sees ONLY abstract factory + abstract products. |
| 2. One factory = one family. Mixing becomes impossible. |
| 3. New family = cheap (add a column). |
| New kind = costly (every factory changes). |
|-----------------------------------------------------------------|
| REAL LIFE : DocumentBuilderFactory (Java XML), |
| DbProviderFactory (.NET), UI look-and-feel kits |
| REMEMBER : "One counter, one matching thali." |
+=================================================================+๐ฏ Practice exercise
Your turn at the counter! Try these tasks:
- Add the Bengali thali. Create
BegunBhaja(starter),LuchiAlurDom(main), andRosogolla(sweet), plus aBengaliThaliFactory. Prove to yourself thatWeddingServiceneeded zero changes. - Festival decoration kits. A school decorates for annual day in two themes: Traditional (marigold garlands, diya lamps, rangoli) and Modern (balloon arches, LED strips, poster art). Model
Garland,Light, andFloorArtas product kinds and build two concrete factories. Write aDecorationCrewclient that decorates one classroom using whichever factory it receives. - Draw before you code. For exercise 2, draw your own wall matrix (rows and columns) and your own versions of Figure 5 and Figure 9. Mark the single state where the theme is chosen.
- Think and write (no code). Meena Tai wants to add a fourth item to every thali: a welcome drink. Explain in 4-5 sentences exactly which files must change, why this is the "expensive direction" of the pattern, and how planning the matrix earlier would have helped.
- College corner challenge. Build the
FakeKitchenFactoryidea for exercise 2: a test family whose products record what was asked of them. Write one unit test that provesDecorationCrewdecorates a classroom correctly without touching any real decoration class.
Excellent work! You now know how Meena Tai guarantees matching families. Next, visit Iqbal Chacha's tailor shop and learn how to assemble one big, complicated object step by step with the Builder pattern.
Frequently asked questions
- What does 'family of products' actually mean?
- It means a group of different objects that are designed to be used together and must match each other. For example, a Gujarati starter, a Gujarati main course, and a Gujarati sweet form one family. A Windows button and a Windows checkbox form another family. The factory guarantees you never mix items from two families.
- How is Abstract Factory different from Factory Method?
- Factory Method has one creation method and makes one product. Abstract Factory is an interface with several creation methods, one for each product kind, and all of them return products from the same matching family. In fact, each method inside an Abstract Factory is usually itself a Factory Method.
- Where do I choose which concrete factory to use?
- In exactly one place, usually at the start of the program. You read a setting (like the menu style or the operating system), create the matching concrete factory once, and pass it to the rest of the code. After that point, no other code knows which family is in use.
- What is the biggest weakness of Abstract Factory?
- Adding a new kind of product is painful. If you add a createDrink method to the factory interface, every single concrete factory must be updated to implement it. The pattern is friendly to new families but unfriendly to new product kinds.
- Is Abstract Factory overkill for small programs?
- Often, yes. The pattern adds many interfaces and classes. If you have only one product variant, or your products do not need to match each other as a set, a simple Factory Method or plain constructors will keep your code shorter and easier to read.
Further reading
Related Lessons
Factory Method Pattern: Let the Branch Decide the Vehicle
Learn the Factory Method design pattern with a simple Indian tiffin service story, easy TypeScript and C# code, diagrams, real examples, and practice.
Builder Pattern: Stitch It Step by Step, Like a Master Tailor
Learn the Builder design pattern with an Indian tailor shop story, fluent TypeScript and C# code, the telescoping constructor problem, and practice tasks.
Singleton Pattern: One Principal for the Whole School
Understand the Singleton design pattern with a school principal story, simple TypeScript and C# code, thread safety, and why many seniors call it an anti-pattern.
Prototype Pattern: Make Copies Like a Xerox Machine, Not From Scratch
Learn the Prototype design pattern with a simple wedding card story, easy TypeScript and Python examples, and a clear shallow vs deep copy demo.