안녕하세요 이번에는 디자인 패턴을 정리해 보려고 합니다.
사실 우테코 6기 시절, 크루 "커찬"의 발표가 저에게는 굉장히 인상 깊었는데요.
따라서 디자인 패턴을 따로 공부하기보다는 프로그래밍을 하며 자연스럽게 익혀왔습니다.
하지만
스프링에서 주요하게 사용되는 싱글톤 패턴,
우테코 체스 미션 중 공부하였던 전략 패턴,
Nginx 트러블 슈팅을 하며 공부하였던 프록시 패턴 등
다양한 패턴을 학습하게 되며 한번쯤은 정리해 보고자 하여 글로 남겨봅니다.

디자인 패턴은 자주 발생하는 소프트웨어 설계 문제를 해결하기 위한 재사용 가능한 설계 템플릿입니다.
특정 상황에서 검증된 설계 방법을 패턴으로 정리해두면, 복잡한 문제를 효율적으로 해결할 수 있고 코드의 유지보수성과 확장성을 높일 수 있습니다.
public class Singleton {
private static final Singleton instance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}
interface Product {
void use();
}
class ConcreteProductA implements Product {
public void use() {
System.out.println("Using Product A");
}
}
class ProductFactory {
public static Product createProduct(String type) {
if ("A".equals(type)) return new ConcreteProductA();
throw new IllegalArgumentException("Unknown type");
}
}
interface Strategy {
void execute();
}
class ConcreteStrategyA implements Strategy {
public void execute() {
System.out.println("Strategy A executed");
}
}
class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public void performStrategy() {
strategy.execute();
}
}
interface Observer {
void update(String message);
}
class Subject {
private List<Observer> observers = new ArrayList<>();
public void addObserver(Observer o) {
observers.add(o);
}
public void notifyObservers(String message) {
for (Observer o : observers) {
o.update(message);
}
}
}
interface Service {
void request();
}
class RealService implements Service {
public void request() {
System.out.println("RealService request executed");
}
}
class ProxyService implements Service {
private RealService realService = new RealService();
public void request() {
System.out.println("Proxy before");
realService.request();
System.out.println("Proxy after");
}
}
List<String> list = Arrays.asList("a", "b", "c");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
const MyModule = (function() {
const privateVar = 'secret';
function privateFunc() {
console.log(privateVar);
}
return {
publicFunc: function() {
privateFunc();
}
};
})();
MyModule.publicFunc();
User → Controller → Model → View → User
User → View ↔ Presenter ↔ Model
View ↔ ViewModel ↔ Model
디자인 패턴이 항상 좋은 것은 아닙니다.
코드가 복잡해졌을 때, 문제를 분리하고 구조화하는 과정에서 자연스럽게 디자인 패턴이 등장할 수 있습니다.
패턴을 억지로 외우고 적용하기보다는, 객체 지향적으로 고민하고 리팩토링을 진행하다 보면 적절한 패턴 형태로 정리되는 경우가 많습니다.
결국, 디자인 패턴은 문제를 해결하기 위한 도구이지 목표 자체는 아니라는 점을 잊지 않아야 합니다.