SOLID AND DESIGN PATTERNS Flashcards

(71 cards)

1
Q

What does SOLID stand for?

A

Single Responsibility
Open/Closed
Liskov Substitution
Interface Segregation
Dependency Inversion

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

SOLID (in one sentence): what is it?

A

A set of OO design principles that help you build code that is easier to change, test, and extend without breaking existing behavior.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

SRP: What is the Single Responsibility Principle?

A

A class/module should have one reason to change (i.e., one primary responsibility).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

SRP: Common code smell that violates it?

A

“God” classes (e.g., OrderService that validates, calculates pricing, persists, sends emails, and logs).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

SRP: Java refactor example (high-level)

A

Split responsibilities:
- OrderValidator
- PricingService
- OrderRepository
- EmailNotifier
OrderService orchestrates.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

OCP: What is the Open/Closed Principle?

A

Software entities should be open for extension but closed for modification (add behavior without editing existing code paths).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

OCP: Typical Java technique to achieve it?

A

Program to interfaces + polymorphism.
Example: DiscountPolicy interface with implementations; add new policies without changing pricing code.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

OCP: When is a switch on type/code a red flag?

A

When every new feature requires editing the switch (violates OCP). Prefer polymorphism/registry when the set of behaviors grows.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

LSP: What is the Liskov Substitution Principle?

A

Subtypes must be substitutable for their base types without altering correctness.
(Clients using the base type shouldn’t need special-case logic.)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

LSP: Rectangle/Square classic issue (why it breaks)?

A

If Square inherits Rectangle but setters enforce equal sides, code that assumes independent width/height can fail. Prefer composition or redesign the abstraction.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

LSP: Quick checklist for a subclass

A
  • Does it strengthen preconditions? (bad)
  • Does it weaken postconditions? (bad)
  • Does it break invariants expected by the base type? (bad)
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

ISP: What is the Interface Segregation Principle?

A

Clients should not be forced to depend on methods they do not use.
Prefer several small interfaces over one “fat” interface.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

ISP: Java example

A

Instead of IMultiFunctionDevice { print(); scan(); fax(); }, use:
Printer, Scanner, Fax interfaces.
Classes implement only what they support.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

DIP: What is the Dependency Inversion Principle?

A

High-level modules should not depend on low-level modules; both should depend on abstractions.
Abstractions should not depend on details; details depend on abstractions.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

DIP: Java practice to implement it

A

Use constructor injection with interfaces.
Example: OrderService(OrderRepository repo, PaymentGateway gateway).
Avoid new ConcreteRepo() inside business logic.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

DIP vs DI: what’s the difference?

A

DIP is a design principle.
DI (Dependency Injection) is a technique/pattern to supply dependencies (often used to achieve DIP).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
17
Q

Cohesion vs coupling (why SOLID cares)

A

High cohesion: related responsibilities together.
Low coupling: fewer/looser dependencies.
SOLID tends to increase cohesion and reduce coupling.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
18
Q

Design Pattern: Singleton — intent

A

Intent: Ensure a class has only one instance and provide a global access point.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
19
Q

Design Pattern: Singleton — Java implementation notes / pitfalls

A

Java notes: Prefer enum Singleton { INSTANCE; } for serialization safety.
Avoid using Singleton as a “global variable” (hurts testability).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
20
Q

Design Pattern: Factory Method — intent

A

Intent: Define an interface for creating an object, but let subclasses decide which class to instantiate.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
21
Q

Design Pattern: Factory Method — Java implementation notes / pitfalls

A

Java notes: Often a static factory (of, valueOf) or overridable create() method.
Use when creation varies by subclass/environment.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
22
Q

Design Pattern: Abstract Factory — intent

A

Intent: Provide an interface for creating families of related objects without specifying concrete classes.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
23
Q

Design Pattern: Abstract Factory — Java implementation notes / pitfalls

A

Java notes: Useful for UI/toolkit families, DB drivers, or platform-specific components.
Often pairs with DI: inject a factory for a family.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
24
Q

Design Pattern: Builder — intent

A

Intent: Separate construction of a complex object from its representation; build step-by-step.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
25
Design Pattern: Builder — Java implementation notes / pitfalls
Java notes: Great for many optional params (avoids telescoping constructors). Immutable objects + fluent builder is common.
26
Design Pattern: Prototype — intent
Intent: Create new objects by copying an existing prototype.
27
Design Pattern: Prototype — Java implementation notes / pitfalls
Java notes: Prefer explicit copy constructors or `clone()` carefully. `Cloneable` is tricky; consider deep copy strategy.
28
Design Pattern: Adapter — intent
Intent: Convert the interface of a class into another interface clients expect.
29
Design Pattern: Adapter — Java implementation notes / pitfalls
Java notes: Wrap legacy APIs. Class adapter (inheritance) is rarer; object adapter (composition) is typical.
30
Design Pattern: Bridge — intent
Intent: Decouple an abstraction from its implementation so both can vary independently.
31
Design Pattern: Bridge — Java implementation notes / pitfalls
Java notes: Abstraction holds a reference to an implementation interface. Example: `Remote` (abstraction) + `Device` (implementation).
32
Design Pattern: Composite — intent
Intent: Compose objects into tree structures to represent part-whole hierarchies; treat leaves and composites uniformly.
33
Design Pattern: Composite — Java implementation notes / pitfalls
Java notes: Common in UI components, file systems. Ensure operations make sense for both leaf and composite.
34
Design Pattern: Decorator — intent
Intent: Attach additional responsibilities to an object dynamically; alternative to subclassing for extension.
35
Design Pattern: Decorator — Java implementation notes / pitfalls
Define a common interface, create a base implementation, then create decorator classes that implement the same interface and wrap another object of that interface to add behavior before or after delegating the call. Java notes: Java I/O streams are classic decorators (`BufferedInputStream`). Keep decorator interface-compatible and order-aware.
36
Design Pattern: Facade — intent
Intent: Provide a simplified interface to a complex subsystem.
37
Design Pattern: Facade — Java implementation notes / pitfalls
Java notes: Great at module boundaries. Facade can reduce coupling but shouldn't hide necessary domain concepts.
38
Design Pattern: Flyweight — intent
Intent: Use sharing to support large numbers of fine-grained objects efficiently.
39
Design Pattern: Flyweight — Java implementation notes / pitfalls
Java notes: Use caches/pools for immutable, shareable state. Separate intrinsic (shared) vs extrinsic (per-use) state.
40
Design Pattern: Proxy — intent
Intent: Provide a surrogate or placeholder to control access to another object.
41
Design Pattern: Proxy — Java implementation notes / pitfalls
Java notes: Common with lazy loading, access control, remote stubs. Java dynamic proxies / bytecode proxies (e.g., AOP) implement this.
42
Design Pattern: Chain of Responsibility — intent
Intent: Pass a request along a chain of handlers; each can handle or pass on.
43
Design Pattern: Chain of Responsibility — Java implementation notes / pitfalls
Java notes: Build pipelines/filters (logging, auth, validation). Beware of missing terminal handler; define default behavior.
44
Design Pattern: Command — intent
Intent: Encapsulate a request as an object, allowing parameterization, queuing, logging, and undo.
45
Design Pattern: Command — Java implementation notes / pitfalls
Java notes: Use functional interfaces/lambdas for simple commands. Store history for undo/redo.
46
Design Pattern: Iterator — intent
Intent: Provide a way to access elements of an aggregate sequentially without exposing its underlying representation.
47
Design Pattern: Iterator — Java implementation notes / pitfalls
Java notes: `Iterator`/`Iterable` built-in. Prefer fail-fast iterators when structure changes unexpectedly.
48
Design Pattern: Mediator — intent
Intent: Define an object that encapsulates how a set of objects interact; promotes loose coupling.
49
Design Pattern: Mediator — Java implementation notes / pitfalls
Java notes: Useful in UI dialogs or workflow coordinators. Avoid turning mediator into a "god" object.
50
Design Pattern: Memento — intent
Intent: Capture and externalize an object's internal state so it can be restored later without violating encapsulation.
51
Design Pattern: Memento — Java implementation notes / pitfalls
Java notes: Used for undo snapshots. Be careful about memory usage; consider incremental diffs.
52
Design Pattern: Observer — intent
Intent: Define a one-to-many dependency so when one object changes state, all dependents are notified.
53
Design Pattern: Observer — Java implementation notes / pitfalls
Java notes: `java.util.Observable/Observer` are deprecated; roll your own or use `PropertyChangeSupport`, reactive streams, etc. Avoid memory leaks: unsubscribe.
54
Design Pattern: State — intent
Intent: Allow an object to alter its behavior when its internal state changes; object appears to change its class.
55
Design Pattern: State — Java implementation notes / pitfalls
Java notes: Represent states as classes implementing a `State` interface. Good when many state-specific branches (`if/switch`) appear.
56
Design Pattern: Strategy — intent
Intent: Define a family of algorithms, encapsulate each, and make them interchangeable.
57
Design Pattern: Strategy — Java implementation notes / pitfalls
Java notes: Use interfaces or lambdas (`Comparator`, `Predicate`). Prefer for runtime selection of behavior.
58
Design Pattern: Template Method — intent
Intent: Define the skeleton of an algorithm in an operation, deferring some steps to subclasses.
59
Design Pattern: Template Method — Java implementation notes / pitfalls
Java notes: Use abstract base class with `final` template method. Prefer composition/strategies if subclassing becomes rigid.
60
Design Pattern: Visitor — intent
Intent: Represent an operation to be performed on elements of an object structure without changing the element classes.
61
Design Pattern: Visitor — Java implementation notes / pitfalls
Java notes: Useful with stable object structures + many operations. Double-dispatch can be verbose; consider pattern matching alternatives (when available).
62
Factory Method vs Abstract Factory (key difference)?
Factory Method: varies **one product** via subclassing/overriding. Abstract Factory: creates **families of related products** via a factory object.
63
Decorator vs Proxy (how to tell them apart)?
Decorator adds behavior/feature. Proxy controls access (lazy, remote, security) and aims to be transparent.
64
Adapter vs Facade (difference)?
Adapter makes one thing look like another (interface conversion). Facade offers a simpler front to a complex subsystem (simplification).
65
Strategy vs State (difference)?
Strategy: caller chooses an algorithm (usually stateless) from a set. State: object changes behavior based on internal state transitions.
66
Composition over inheritance (why)?
Composition is more flexible: change behavior by swapping collaborators instead of being locked into an inheritance hierarchy. Helps with OCP and LSP.
67
When should you avoid patterns?
When simple code is clearer. Patterns add indirection; use them to solve repeated/complex change problems, not as decoration.
68
What is "program to an interface" (in Java)?
Depend on `interface`/abstract types rather than concrete classes. This enables substitution (testing, swapping implementations) and supports OCP/DIP.
69
What is the role of UML-like participants in GoF patterns (Creator/Client/Receiver etc.)?
They describe **responsibilities** (who creates, who calls, who implements) so you can map the idea into your codebase regardless of language/framework.
70
SOLID vs design patterns (relationship)?
SOLID = principles (guidelines). Design patterns = reusable solutions to recurring design problems. Patterns often help you apply SOLID, but are not mandatory.
71
How do you spot an overused Singleton?
When many classes call `Singleton.getInstance()` (hidden dependency), tests are hard, and state leaks between tests. Prefer DI + explicit dependencies.