27 · 32 · 5 min
Four patterns worth knowing
A design pattern is a named solution to a problem that keeps coming back. Four are worth knowing before any others.
Singleton
One instance, globally reachable.
class Config {
private static Config instance;
private Config() { }
public static synchronized Config get() {
if (instance == null) instance = new Config();
return instance;
}
}Factory
Creation behind a method, so the caller does not name a concrete class.
static Channel create(String type) {
return switch (type) {
case "email" -> new EmailChannel();
case "sms" -> new SmsChannel();
default -> throw new IllegalArgumentException(type);
};
}The switch has not gone away. It has been moved to one place, which is the point: the rest of the code no longer knows the concrete types exist.
Observer
Objects subscribe, and are told when something happens.
interface Listener { void onSubmit(Submission s); }
class Judge {
private final List<Listener> listeners = new ArrayList<>();
void add(Listener l) { listeners.add(l); }
private void finished(Submission s) {
for (Listener l : listeners) l.onSubmit(s);
}
}Adding a new reaction means adding a listener, not editing the judge. Open closed again.
Strategy
An algorithm chosen at runtime. That is exactly what page eight built: the Channel interface with one implementation per channel is the strategy pattern, arrived at by fixing a problem rather than by picking a pattern.