IT Developer/Java

Java 기초 <17. Java 디자인 패턴 – 싱글톤, 팩토리, 전략 패턴 등>

TEMA_ 2025. 3. 18. 09:11
반응형

자바 Java

17. Java 디자인 패턴 – 싱글톤, 팩토리, 전략 패턴 등

 

안녕하세요! 태마입니다.

Java 기초 강좌입니다.

 

강좌의 경우 

1. 주제 간단 정리

2. 상세 주제 정리

으로 이루어져 있습니다.

 

자바 Java

포스팅 시작하겠습니다 :)

1. 주제 간단 정리

 

1. 디자인 패턴(Design Pattern) 개념

디자인 패턴소프트웨어 설계 시 발생할 수 있는 문제에 대한 해결책을 일반화하여 제공하는 재사용 가능한 솔루션입니다.
✔ 디자인 패턴은 다양한 상황에 맞는 해결책을 제공하고, 코드의 재사용성을 높이며, 유지보수를 용이하게 만듭니다.
✔ 디자인 패턴은 문제의 유형해결 방법을 구체화한 것입니다.

📌 디자인 패턴의 주요 장점
재사용성 : 패턴을 사용하면 이미 검증된 해결책을 반복적으로 활용
유지보수 용이성 : 일관된 설계 방식을 통해 코드 수정과 확장이 쉬움
표준화된 해결책 : 여러 개발자들이 이해할 수 있는 표준화된 방법 제공


 

2. 디자인 패턴의 분류

디자인 패턴은 세 가지 주요 카테고리로 나눌 수 있습니다.

  • 생성 패턴(Creational Patterns) : 객체 생성에 관한 패턴
  • 구조 패턴(Structural Patterns) : 클래스와 객체의 구조에 관한 패턴
  • 행위 패턴(Behavioral Patterns) : 객체 간 상호작용과 책임에 관한 패턴

📌 생성 패턴은 객체 생성 방법을 최적화하고, 구조 패턴은 객체 간 관계를 최적화하며, 행위 패턴은 객체 간의 상호작용을 최적화하는 데 사용됩니다.


 

3. 디자인 패턴 사용 시 주의점

디자인 패턴은 매우 유용하지만, 무분별한 사용은 복잡성을 증가시킬 수 있습니다.
✔ 패턴을 사용하기 전에 문제의 성격어떤 패턴이 적합한지 잘 판단해야 합니다.
단순한 문제에 복잡한 패턴을 적용하면 오히려 유지보수성이 떨어질 수 있습니다.

📌 디자인 패턴은 항상 필요한 경우에만 사용하는 것이 좋습니다.

반응형

2. 상세 주제 정리

 

1. 싱글톤 패턴(Singleton Pattern)

싱글톤 패턴애플리케이션에서 단 하나의 인스턴스만 존재하도록 보장하는 패턴입니다.
✔ 주로 애플리케이션의 설정 정보로그 처리, 데이터베이스 연결을 위한 객체에 사용됩니다.
인스턴스를 한 번만 생성하고, 이후에는 생성된 인스턴스를 재사용합니다.

싱글톤 패턴 구현 예제

public class Singleton {
    private static Singleton instance;

    private Singleton() {}  // 생성자를 private로 선언하여 외부에서 인스턴스를 생성할 수 없도록 함.

    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

📌 getInstance() 메서드는 인스턴스가 없을 때만 생성하며, 동일 인스턴스를 재사용.


2. 팩토리 패턴(Factory Pattern)

팩토리 패턴객체를 생성하는 인터페이스를 제공하고, 그 구현을 서브클래스에서 맡는 패턴입니다.
✔ 팩토리 패턴은 객체 생성 로직을 클라이언트 코드와 분리하여, 객체 생성을 보다 유연하고 확장 가능하게 만듭니다.
✔ 팩토리 메서드를 사용하면 객체의 생성 과정을 숨기고 클라이언트가 이를 사용할 수 있도록 합니다.

팩토리 패턴 구현 예제

// 제품 인터페이스
interface Product {
    void create();
}

// 구체적인 제품 클래스
class ConcreteProductA implements Product {
    public void create() {
        System.out.println("Product A created.");
    }
}

class ConcreteProductB implements Product {
    public void create() {
        System.out.println("Product B created.");
    }
}

// 팩토리 클래스
class ProductFactory {
    public Product createProduct(String type) {
        if ("A".equals(type)) {
            return new ConcreteProductA();
        } else if ("B".equals(type)) {
            return new ConcreteProductB();
        }
        return null;
    }
}

📌 팩토리 클래스는 객체의 생성 로직을 숨기고, 클라이언트 코드에서 직접 객체를 생성하지 않도록 함.


3. 전략 패턴(Strategy Pattern)

전략 패턴동적으로 알고리즘을 교체할 수 있도록 하는 패턴입니다.
✔ 다양한 알고리즘을 인터페이스로 정의하고, 실행 시 동적으로 선택하여 사용할 수 있게 합니다.
알고리즘을 클래스별로 캡슐화하고, 클라이언트가 사용할 알고리즘을 동적으로 선택할 수 있도록 만듭니다.

전략 패턴 구현 예제

// 전략 인터페이스
interface Strategy {
    int execute(int a, int b);
}

// 구체적인 전략 클래스
class AddStrategy implements Strategy {
    public int execute(int a, int b) {
        return a + b;
    }
}

class SubtractStrategy implements Strategy {
    public int execute(int a, int b) {
        return a - b;
    }
}

// 컨텍스트 클래스
class Calculator {
    private Strategy strategy;

    public Calculator(Strategy strategy) {
        this.strategy = strategy;
    }

    public int calculate(int a, int b) {
        return strategy.execute(a, b);
    }
}

📌 전략 패턴은 동적으로 알고리즘을 교체할 수 있게 하여, 코드의 유연성을 높임.


4. 데코레이터 패턴(Decorator Pattern)

데코레이터 패턴기존 객체의 기능을 확장할 수 있는 패턴입니다.
✔ 객체를 감싸는(wrapper) 형태로 기능을 추가하며, 원본 객체의 인터페이스를 변경하지 않고도 기능을 동적으로 확장할 수 있습니다.

데코레이터 패턴 구현 예제

// 기본 인터페이스
interface Coffee {
    double cost();
}

// 구체적인 객체
class SimpleCoffee implements Coffee {
    public double cost() {
        return 5;
    }
}

// 데코레이터 클래스
class MilkDecorator implements Coffee {
    private Coffee coffee;

    public MilkDecorator(Coffee coffee) {
        this.coffee = coffee;
    }

    public double cost() {
        return coffee.cost() + 2;  // 우유 추가 비용
    }
}

class SugarDecorator implements Coffee {
    private Coffee coffee;

    public SugarDecorator(Coffee coffee) {
        this.coffee = coffee;
    }

    public double cost() {
        return coffee.cost() + 1;  // 설탕 추가 비용
    }
}

📌 데코레이터 패턴을 사용하면 객체의 기능을 유연하게 확장할 수 있음.


5. 옵저버 패턴(Observer Pattern)

옵저버 패턴객체의 상태 변화에 따라 여러 객체가 자동으로 갱신되는 패턴입니다.
주체(Subject) 객체의 상태가 변할 때마다 종속된(Observer) 객체들에게 알림을 주어, 자동으로 상태가 갱신되도록 합니다.
✔ 이벤트 기반 시스템에서 많이 사용되며, UI 업데이트이벤트 처리에 유용합니다.

옵저버 패턴 구현 예제

import java.util.*;

// 옵저버 인터페이스
interface Observer {
    void update(String message);
}

// 주체 클래스
class Subject {
    private List<Observer> observers = new ArrayList<>();
    
    public void addObserver(Observer observer) {
        observers.add(observer);
    }

    public void notifyObservers(String message) {
        for (Observer observer : observers) {
            observer.update(message);
        }
    }
}

// 구체적인 옵저버 클래스
class ConcreteObserver implements Observer {
    private String name;
    
    public ConcreteObserver(String name) {
        this.name = name;
    }

    public void update(String message) {
        System.out.println(name + " received: " + message);
    }
}

📌 옵저버 패턴은 주체 객체의 상태 변화에 따라 여러 객체가 자동으로 갱신되도록 함.


지금까지 주요 Java 디자인 패턴에 대해 배웠어요!
👉 "이제 테스트 및 TDD 개념에 대해 배우고 싶다면?"
다음 회차에서 JUnit, Mockito, TDD에 대해 다뤄봅시다!

반응형