Concept: Ensures only one instance of a class or module exists.
When: Shared services (e.g. config, logging, API clients).
// singleton.js
let instance;
class Logger {
constructor() {
if (instance) return instance;
instance = this;
}
log(msg) {
console.log(msg);
}
}
export const logger = new Logger();
In React: Use in service layers outside the component tree.
Concept: Create components based on input type.
const componentFactory = (type) => {
switch (type) {
case 'text': return <TextInput />;
case 'select': return <SelectInput />;
default: return <DefaultInput />;
}
};
When: Dynamic forms or dashboards with config-driven UIs.
Concept: Step-by-step construction of a UI element.
class CardBuilder {
constructor() {
this.card = {};
}
setTitle(title) { this.card.title = title; return this; }
setContent(content) { this.card.content = content; return this; }
build() {
return <Card {...this.card} />;
}
}
When: UI components with many optional parts (e.g. modals).
Concept: Share behavior via prototypes instead of classes.
In React: Rare directly, but used under-the-hood in JS. Useful for extending objects (e.g. custom event systems or polyfills).
const proto = {
greet() { return `Hello ${this.name}`; }
};
const user = Object.create(proto);
user.name = "Alice";
Concept: Add behavior without modifying the original.
React Example (HOC):
const withLogger = (Component) => (props) => {
console.log('Rendered with props:', props);
return <Component {...props} />;
};
When: Cross-cutting concerns (auth, logging, metrics).
Concept: Translate one interface to another.
const legacyApi = { fetchData: () => fetch('/old-endpoint') };
const apiAdapter = {
getData: () => legacyApi.fetchData().then(res => res.json())
};
In React: Wrap third-party APIs in standardized service modules.
Concept: Treat individual and composite components uniformly.
const TreeNode = ({ node }) => (
<li>
{node.label}
{node.children && (
<ul>
{node.children.map((child) => (
<TreeNode node={child} />
))}
</ul>
)}
</li>
);
Concept: Provide a unified interface to complex subsystems.
// apiFacade.js
export const api = {
getUser: () => fetch('/user'),
getSettings: () => fetch('/settings')
};
React Use: Centralized service modules for clean component logic.
Concept: Control access to an object (e.g., caching, validation).
const api = new Proxy(fetch, {
apply(target, thisArg, args) {
console.log('Fetching:', args[0]);
return target(...args);
}
});
When: Logging, caching, lazy-loading.
Concept: Encapsulate logic in a self-contained unit.
// counterModule.js
let count = 0;
export const counter = {
increment: () => ++count,
get: () => count
};
React Use: Shared utility logic or stateful services.
Concept: A subject notifies observers on state change.
class EventBus {
observers = [];
subscribe(fn) { this.observers.push(fn); }
notify(data) { this.observers.forEach(fn => fn(data)); }
}
React Use: Pub/sub for state sharing across micro-frontends or tabs.
Concept: Swap algorithms/strategies at runtime.
const sortStrategies = {
byName: (a, b) => a.name.localeCompare(b.name),
byAge: (a, b) => a.age - b.age
};
const sortData = (data, strategy) => data.sort(sortStrategies[strategy]);
React Use: Dynamic UI logic (filters, layouts, validations).
Concept: Encapsulate user commands (undo/redo).
class Command {
execute() {}
undo() {}
}
class AddItemCommand extends Command {
execute() { /* add */ }
undo() { /* remove */ }
}
React Use: Form builders, canvas editors.
Concept: Central object coordinates communication.
const mediator = {
notify: (sender, event) => {
if (event === 'save') console.log(`${sender} triggered save`);
}
};
React Use: Dialog systems or loosely-coupled dashboards.
Concept: Pass request along a chain until handled.
const handlerA = (req, next) => req.type === 'A' ? 'Handled A' : next(req);
const handlerB = (req) => req.type === 'B' ? 'Handled B' : 'Unhandled';
const chain = (req) => handlerA(req, handlerB);
React Use: Middleware-like UI logic, form validation chains.
Concept: Function that adds behavior to a component.
const withLoading = (Component) => ({ isLoading, ...rest }) =>
isLoading ? <Spinner /> : <Component {...rest} />;
Pros: Reusability, separation of concerns
Cons: Prop collision, nesting complexity
Concept: Share logic via a function-as-child.
<MouseTracker render={({ x, y }) => <Cursor x={x} y={y} />} />
Use: Reusable logic without HOC pitfalls.
Concept: Use React Context to inject global values.
const ThemeContext = React.createContext();
const ThemeProvider = ({ children }) => {
const [theme] = useState("dark");
return <ThemeContext.Provider value={theme}>{children}</ThemeContext.Provider>;
};
Use: Auth, theming, config, localization.
Concept: Separate logic (container) from view (presentational).
// Container
const UserContainer = () => {
const [user, setUser] = useState(null);
return <UserProfile user={user} />;
};
// Presentational
const UserProfile = ({ user }) => <div>{user?.name}</div>;
Use: Testing, reuse, separation of concerns.
Goal: Help devs choose patterns based on intent, not just familiarity.