Design Patterns (GoF and modern) Module 2
Creational patterns: Factory Method to Singleton interview questions
Interview questions on “Creational patterns: Factory Method to Singleton”: warm-ups, then what each harder question tests and how a good answer starts.
Warm-up questions
Short questions with short answers, each answered in full.
-
Fresher
What is the difference between Factory Method and a simple factory function?
Answered in the lesson Factory Method: defer which class to create
-
Fresher
How does Abstract Factory differ from Factory Method?
Answered in the lesson Abstract Factory: families of related objects
-
Fresher
What problem does the Builder pattern solve that a constructor with many parameters does not?
Answered in the lesson Builder: step-by-step object construction
-
Fresher
What is the difference between a shallow copy and a deep copy?
-
Fresher to mid
Why do many teams avoid the Singleton pattern, and what do they use instead?
Answered in the lesson Singleton: one instance and its real costs
Questions with model answers
What each question tests, the first step of a good answer and the follow-ups to expect.
-
Mid to senior
Your payment SDK creates its 14 payment methods in one switch statement, and partners now want to add their own without forking the SDK. Design the creation API. How do you handle two partners registering the same name, the order in which extensions load, and a developer who cannot tell which methods are installed?
- What it tests
- Turning a closed switch into an extension point: registry keys, duplicate rules, load order, discovery and a core that stays testable.
- First step
- Separate deciding from using. Define the PaymentMethod interface the SDK needs, then a registry from a stable, namespaced key such as "acme.wallet" to a factory. Decide the duplicate rule first, because it shapes the whole API: refuse a taken key loudly instead of letting the last registration win.
- Follow-ups
-
- Partners ship their methods as separate packages. How are they found and loaded?
- Two versions of the same extension are installed. What happens?
- How do tests swap in a fake payment method without touching the shared registry?
From the lesson Factory Method: defer which class to create
Model answer, Pro. Model answers open with any pass; prices are in the notice on this page.Opening the model answers with your pass…
Model answers open with any MySmartCoPilot pass.
- Pro pass · 1 week₹79$2.99
- 30 days₹179$5.99
- 1 year₹1,699$45
One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.
Passes can’t be bought right now, so the model answers can’t be opened at the moment. If you have a pass, enter your licence key.
It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).
In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Mid
300 tests need a fake SMS sender, but the production code calls the SmsSender constructor directly in 40 places. Plan the change to a factory as a sequence of small commits that each keep the build green. Which seam do you introduce first, and how do you stop new direct calls from appearing?
- What it tests
- Introducing a creation seam in legacy code safely, choosing between constructor injection, a factory and a registry, and keeping the migration enforceable.
- First step
- Count the 40 call sites by the object that owns them, because the seam belongs where the sender is used, not where it is built. Give the first owner a constructor parameter with the current behaviour as its default, so nothing changes for callers, and move one owner per commit.
- Follow-ups
-
- Some of the 40 calls are in static helper functions. What do you do with those?
- When would a registry be worse than constructor injection here?
- How do you prove the tests now use the fake and never the real sender?
From the lesson Factory Method: defer which class to create
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Mid to senior
Your service has a production family (Postgres repositories, the system clock, UUID ids) and an in-memory test family. Every repository now needs a cache in front of it. What changes in the factories, and how do you make it impossible for a test to pair a real cache with a fake repository?
- What it tests
- Adding a product type to an existing Abstract Factory, keeping families consistent by construction rather than by convention, and designing a test family that stays honest.
- First step
- Decide whether the cache is a product of its own or part of how a repository is built. If it wraps the repository, let each factory return the already-wrapped repository, so no caller ever assembles a cache and a repository itself; then mixing is not something a test can even write.
- Follow-ups
-
- Should the in-memory family have a cache at all?
- How do you show that both families behave the same?
- A third family for a staging environment appears. What do you check?
From the lesson Abstract Factory: families of related objects
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Senior to staff
Thirty partner themes implement your WidgetFactory interface, and version 2 needs a date picker widget. How do you add it without breaking the existing themes, and what does each option cost in consistency and support?
- What it tests
- Evolving a published Abstract Factory interface: default methods, optional capabilities, versioned interfaces, adapters and a deprecation plan, judged by whether screens can still mix families.
- First step
- State the constraint: a new abstract method breaks all thirty themes at once, in code you do not own. Then list the options that keep old themes working, a default method, an optional capability or a second interface, and judge each one by the question the pattern exists for: can a screen now end up mixing two families?
- Follow-ups
-
- What does a screen show when its theme has no date picker?
- How long do you keep supporting version 1 themes?
- How do you write a default that does not mix styles?
From the lesson Abstract Factory: families of related objects
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Mid to senior
You own the HTTP client library that 200 services use. Design its configuration API: a builder, an options object or functional options? How do you add an option in version 2 without breaking any caller, and where do you check combinations such as retries without a timeout?
- What it tests
- Choosing a construction style per language, keeping a widely used API compatible as options grow, and validating rules that span several options in one place.
- First step
- Separate what every client must have (a base URL) from what may be left to defaults (timeouts, retries, headers), and make only the first required. Then pick the style that lets you add an optional setting without changing a single existing call, and name the one place where the combinations are checked.
- Follow-ups
-
- A team needs a setting you never planned for. What is the escape hatch?
- How do you deprecate an option that turned out to be dangerous?
- Where do defaults live, and how does a caller see which ones were applied?
From the lesson Builder: step-by-step object construction
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Mid to senior
A game starts every match by deep-copying a level template of 5,000 entities, and match start now takes about 350 ms in Python. How do you make it fast without two matches ever sharing state that one of them changes?
- What it tests
- Measuring before optimising, separating immutable from per-match state, choosing between deepcopy, hand-written copies, copy-on-write and structural sharing, and proving that copies stay independent.
- First step
- Measure what deepcopy visits: for each entity, list which parts a match can change (position, health, inventory) and which it never changes (sprites, rules, names). Only the first group needs a copy per match; the second can be shared if it is truly immutable.
- Follow-ups
-
- How do you prove that two matches never share state?
- Most entities are never touched in a match. Can you avoid copying them at all?
- Where does copy-on-write go wrong?
From the lesson Prototype: create objects by copying
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Mid to senior
A service caches one parsed configuration per plan and hands every tenant a copy. A bug report shows one tenant's custom setting appearing for another tenant on the same plan. Walk through the diagnosis and the fix.
- What it tests
- Diagnosing shared mutable state behind a shallow copy, choosing the copy depth, making a cached prototype immutable, and handling the incident.
- First step
- Find how the copy is made. A shallow copy of a configuration shares its nested dictionaries, so one tenant's override written into a nested section lands in the cached prototype and in every copy made after it. Reproduce it with two tenants in a test before changing any code.
- Follow-ups
-
- Is a deep copy on every request acceptable?
- How do you make the cached prototype impossible to change?
- How do you find which tenants were affected?
From the lesson Prototype: create objects by copying
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Mid to senior
A service reads its configuration through Config.getInstance() in 140 places, and tests reset it with a setInstance() hook that people forget, so the suite fails in some orders. Plan the move to injected configuration without one big change, and say how you stop new calls to getInstance().
- What it tests
- Removing a global step by step: constructor injection with temporary defaults, a composition root, keeping the build green, and enforcing the end state.
- First step
- Group the 140 calls by the class that makes them, because each class needs one constructor parameter, not one change per call. Start with the classes that the flaky tests touch, since they pay back first, and keep getInstance() working until the last caller is gone.
- Follow-ups
-
- Some calls are in static utility functions. What then?
- Part of the configuration changes while the service runs. How is it passed?
- What happens to setInstance() at the end?
From the lesson Singleton: one instance and its real costs
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Mid to senior
After each deploy, 2,000 requests arrive within a second, and the lazily created client for the tax service is built about 40 times; the tax service then rate-limits you. Explain the cause, fix it in a language you know, and say how you would test the fix.
- What it tests
- Diagnosing a lazy-initialisation race, choosing a once-only construct or eager creation, deciding what happens when initialisation fails, and testing concurrency deterministically.
- First step
- Look at how the client is created. A null check followed by construction, without a lock, lets every request that arrives during the slow first connection build a client of its own. Replace it with the language's once-only construct, so callers that arrive meanwhile wait for the first.
- Follow-ups
-
- What should happen when the first initialisation fails?
- Would creating the client at start-up be better?
- How do you write a test that fails every time on the old code?
From the lesson Singleton: one instance and its real costs
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
All Design Patterns (GoF and modern) interview questions · The Design Patterns (GoF and modern) track