3. 행위 패턴 (Behavioral Patterns)
행위 패턴은 객체나 클래스 간의 상호작용과 책임 분배를 정의하는 패턴이다.
이 패턴은 객체 간의 통신 방법과 객체 간의 결합도를 줄이는 데 초점을 맞춘다.
---
3.1 Chain of Responsibility Pattern (책임 연쇄 패턴)
개념:
요청을 처리할 수 있는 객체들을 연결된 체인으로 구성하고, 각 객체가 요청을 처리하거나 다음 객체로 전달하는 패턴.
구조 다이어그램:
+------------+
| Handler |
+------------+
|
+------------+
| Concrete1 |
+------------+
|
+------------+
| Concrete2 |
+------------+
예제 코드:
abstract class Handler {
protected Handler next;
public void setNext(Handler next) {
this.next = next;
}
public abstract void handleRequest(String request);
}
class ConcreteHandler1 extends Handler {
public void handleRequest(String request) {
if (request.equals("A")) {
System.out.println("Handler1 handled request: " + request);
} else if (next != null) {
next.handleRequest(request);
}
}
}
class ConcreteHandler2 extends Handler {
public void handleRequest(String request) {
if (request.equals("B")) {
System.out.println("Handler2 handled request: " + request);
} else if (next != null) {
next.handleRequest(request);
}
}
}
public class Main {
public static void main(String[] args) {
Handler handler1 = new ConcreteHandler1();
Handler handler2 = new ConcreteHandler2();
handler1.setNext(handler2);
handler1.handleRequest("A");
handler1.handleRequest("B");
handler1.handleRequest("C");
}
}
출력:
Handler1 handled request: A
Handler2 handled request: B
장단점:
장점: 요청 처리 객체를 분리하여 코드의 응집도를 높임, 새로운 처리자를 추가하기 용이함
단점: 체인의 길이가 길어질 경우 성능 저하 가능, 요청이 모두 거부될 경우 에러가 발생할 수 있음
---
3.2 Command Pattern (커맨드 패턴)
개념:
요청을 객체로 캡슐화하여 요청에 필요한 모든 정보를 저장하고, 나중에 해당 요청을 재실행하거나 취소할 수 있도록 하는 패턴.
구조 다이어그램:
+----------+
| Command |
+----------+
|
+-------------+
| ConcreteCmd |
+-------------+
|
+---------+
| Invoker |
+---------+
예제 코드:
interface Command {
void execute();
}
class Light {
public void turnOn() {
System.out.println("Light is ON");
}
}
class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
public void execute() {
light.turnOn();
}
}
class RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
}
}
public class Main {
public static void main(String[] args) {
Light light = new Light();
Command lightOn = new LightOnCommand(light);
RemoteControl remote = new RemoteControl();
remote.setCommand(lightOn);
remote.pressButton();
}
}
출력:
Light is ON
장단점:
장점: 요청을 객체로 캡슐화하여 재실행, 취소 가능
단점: 명령 객체가 많아질 경우 메모리 사용이 증가할 수 있음
---
3.3 Interpreter Pattern (인터프리터 패턴)
개념:
언어의 문법을 클래스화하여, 각 클래스가 해당 언어의 규칙을 해석하고 실행하도록 하는 패턴.
구조 다이어그램:
+-----------+
| Context |
+-----------+
|
+-----------+
| Expression |
+-----------+
|
+-------------------+
| ConcreteExpression |
+-------------------+
예제 코드:
interface Expression {
boolean interpret(String context);
}
class TerminalExpression implements Expression {
private String data;
public TerminalExpression(String data) {
this.data = data;
}
public boolean interpret(String context) {
return context.contains(data);
}
}
public class Main {
public static void main(String[] args) {
Expression isJava = new TerminalExpression("Java");
Expression isPython = new TerminalExpression("Python");
System.out.println(isJava.interpret("I love Java"));
System.out.println(isPython.interpret("I love Python"));
}
}
출력:
true
true
장단점:
장점: 언어의 문법을 객체로 정의하여 재사용이 가능함
단점: 새로운 규칙이 추가될 경우 클래스가 급격히 증가할 수 있음
---
3.4 Iterator Pattern (이터레이터 패턴)
개념:
컬렉션 객체의 요소들을 순차적으로 접근할 수 있도록 하는 패턴.
구조 다이어그램:
+----------+
| Iterator |
+----------+
|
+----------+
| Concrete |
+----------+
예제 코드:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> items = new ArrayList<>();
items.add("Item1");
items.add("Item2");
items.add("Item3");
Iterator<String> iterator = items.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
출력:
Item1
Item2
Item3
장단점:
장점: 컬렉션의 내부 구조를 노출하지 않고 순차 접근이 가능함
단점: 컬렉션이 변경되면 이터레이터도 함께 수정해야 함
---
여기까지 책임 연쇄 패턴, 커맨드 패턴, 인터프리터 패턴, 이터레이터 패턴의 출력부와 장단점을 모두 포함하여 작성했어!
남은 Mediator, Memento, Observer, State, Strategy, Template Method, Visitor 패턴도 이어서 작성할게! 😊👍
3.5 Mediator Pattern (중재자 패턴)
개념:
객체 간의 통신을 중재자(Mediator)를 통해서만 수행하도록 하여 객체 간의 결합을 줄이는 패턴.
구조 다이어그램:
+-----------+
| Mediator |
+-----------+
|
+-------+-------+
| |
+-----------+ +-----------+
| Colleague1 | | Colleague2 |
+-----------+ +-----------+
예제 코드:
interface Mediator {
void sendMessage(String message, Colleague colleague);
}
abstract class Colleague {
protected Mediator mediator;
public Colleague(Mediator mediator) {
this.mediator = mediator;
}
}
class ConcreteColleague1 extends Colleague {
public ConcreteColleague1(Mediator mediator) {
super(mediator);
}
public void send(String message) {
mediator.sendMessage(message, this);
}
public void receive(String message) {
System.out.println("Colleague1 received: " + message);
}
}
class ConcreteColleague2 extends Colleague {
public ConcreteColleague2(Mediator mediator) {
super(mediator);
}
public void receive(String message) {
System.out.println("Colleague2 received: " + message);
}
}
class ConcreteMediator implements Mediator {
private ConcreteColleague1 colleague1;
private ConcreteColleague2 colleague2;
public void setColleague1(ConcreteColleague1 colleague1) {
this.colleague1 = colleague1;
}
public void setColleague2(ConcreteColleague2 colleague2) {
this.colleague2 = colleague2;
}
public void sendMessage(String message, Colleague colleague) {
if (colleague == colleague1) {
colleague2.receive(message);
} else {
colleague1.receive(message);
}
}
}
public class Main {
public static void main(String[] args) {
ConcreteMediator mediator = new ConcreteMediator();
ConcreteColleague1 colleague1 = new ConcreteColleague1(mediator);
ConcreteColleague2 colleague2 = new ConcreteColleague2(mediator);
mediator.setColleague1(colleague1);
mediator.setColleague2(colleague2);
colleague1.send("Hello");
}
}
출력:
Colleague2 received: Hello
장단점:
장점: 객체 간의 통신을 중앙에서 관리하여 결합도를 낮춤
단점: 중재자 객체에 로직이 집중되면 유지보수가 어려워짐
---
3.6 Memento Pattern (메멘토 패턴)
개념:
객체의 상태를 저장하고, 나중에 이를 복원할 수 있도록 하는 패턴.
구조 다이어그램:
+-----------+
| Originator |
+-----------+
|
+-----------+
| Memento |
+-----------+
|
+-----------+
| Caretaker |
+-----------+
예제 코드:
class Memento {
private String state;
public Memento(String state) {
this.state = state;
}
public String getState() {
return state;
}
}
class Originator {
private String state;
public void setState(String state) {
this.state = state;
}
public Memento saveStateToMemento() {
return new Memento(state);
}
public void getStateFromMemento(Memento memento) {
state = memento.getState();
}
public void showState() {
System.out.println("Current State: " + state);
}
}
class Caretaker {
private Memento memento;
public void saveState(Memento memento) {
this.memento = memento;
}
public Memento restoreState() {
return memento;
}
}
public class Main {
public static void main(String[] args) {
Originator originator = new Originator();
Caretaker caretaker = new Caretaker();
originator.setState("State #1");
originator.showState();
caretaker.saveState(originator.saveStateToMemento());
originator.setState("State #2");
originator.showState();
originator.getStateFromMemento(caretaker.restoreState());
originator.showState();
}
}
출력:
Current State: State #1
Current State: State #2
Current State: State #1
장단점:
장점: 객체의 상태를 쉽게 저장하고 복원할 수 있음
단점: 저장할 상태가 많을 경우 메모리 사용이 증가할 수 있음
---
3.7 Observer Pattern (옵저버 패턴)
개념:
객체의 상태가 변경되면, 의존하는 객체들에게 자동으로 알림이 전달되는 패턴.
구조 다이어그램:
+----------+
| Subject |
+----------+
|
+----------+
| Observer |
+----------+
예제 코드:
import java.util.ArrayList;
import java.util.List;
interface Observer {
void update(String 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);
}
}
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);
}
}
}
public class Main {
public static void main(String[] args) {
Subject subject = new Subject();
Observer observer1 = new ConcreteObserver("Observer1");
Observer observer2 = new ConcreteObserver("Observer2");
subject.addObserver(observer1);
subject.addObserver(observer2);
subject.notifyObservers("Hello, Observers!");
}
}
출력:
Observer1 received: Hello, Observers!
Observer2 received: Hello, Observers!
장단점:
장점: 객체 간의 의존성을 줄이고, 확장성이 높음
단점: 옵저버가 많을 경우 알림 전달이 지연될 수 있음
3.8 State Pattern (상태 패턴)
개념:
객체의 상태에 따라 동작이 달라지도록 설계하는 패턴.
상태 전환 로직을 개별 클래스로 분리하여 코드의 응집도를 높이고 관리하기 쉽게 한다.
구조 다이어그램:
+---------+
| Context |
+---------+
|
+---------+
| State |
+---------+
|
+-----------+-----------+
| |
+---------+ +---------+
| Concrete | | Concrete |
| State A | | State B |
+---------+ +---------+
예제 코드:
interface State {
void handle(Context context);
}
class StartState implements State {
public void handle(Context context) {
System.out.println("Starting...");
context.setState(this);
}
public String toString() {
return "Start State";
}
}
class StopState implements State {
public void handle(Context context) {
System.out.println("Stopping...");
context.setState(this);
}
public String toString() {
return "Stop State";
}
}
class Context {
private State state;
public void setState(State state) {
this.state = state;
}
public State getState() {
return state;
}
}
public class Main {
public static void main(String[] args) {
Context context = new Context();
StartState startState = new StartState();
startState.handle(context);
System.out.println(context.getState().toString());
StopState stopState = new StopState();
stopState.handle(context);
System.out.println(context.getState().toString());
}
}
출력:
Starting...
Start State
Stopping...
Stop State
장단점:
장점: 상태 전환 로직을 각 상태 객체로 분리하여 관리 용이
단점: 상태 클래스가 많아질 경우 코드가 복잡해짐
---
3.9 Strategy Pattern (전략 패턴)
개념:
여러 알고리즘을 각각의 클래스로 캡슐화하고, 런타임에 알고리즘을 교체할 수 있도록 설계하는 패턴.
구조 다이어그램:
+---------+
| Context |
+---------+
|
+---------+
| Strategy |
+---------+
|
+----------+----------+
| |
+---------+ +---------+
| Concrete | | Concrete |
| StrategyA| | StrategyB|
+---------+ +---------+
예제 코드:
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 Context {
private Strategy strategy;
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
public int executeStrategy(int a, int b) {
return strategy.execute(a, b);
}
}
public class Main {
public static void main(String[] args) {
Context context = new Context();
context.setStrategy(new AddStrategy());
System.out.println("Addition: " + context.executeStrategy(5, 3));
context.setStrategy(new SubtractStrategy());
System.out.println("Subtraction: " + context.executeStrategy(5, 3));
}
}
출력:
Addition: 8
Subtraction: 2
장단점:
장점: 알고리즘을 유연하게 교체 가능, 코드 재사용성 높음
단점: 전략 클래스가 많아질 경우 코드가 복잡해짐
---
3.10 Template Method Pattern (템플릿 메서드 패턴)
개념:
상위 클래스에서 전체 알고리즘의 구조를 정의하고, 하위 클래스에서 일부 단계를 구체화하는 패턴.
구조 다이어그램:
+-----------------+
| AbstractClass |
+-----------------+
|
+-----------------+
| ConcreteClass |
+-----------------+
예제 코드:
abstract class Game {
abstract void initialize();
abstract void startPlay();
abstract void endPlay();
public final void play() {
initialize();
startPlay();
endPlay();
}
}
class Football extends Game {
void initialize() { System.out.println("Football Game Initialized."); }
void startPlay() { System.out.println("Football Game Started."); }
void endPlay() { System.out.println("Football Game Finished."); }
}
public class Main {
public static void main(String[] args) {
Game game = new Football();
game.play();
}
}
출력:
Football Game Initialized.
Football Game Started.
Football Game Finished.
장단점:
장점: 알고리즘 구조를 재사용 가능, 코드 중복 감소
단점: 상속을 통해 구현되므로 클래스 간의 결합도가 높아질 수 있음
---
3.11 Visitor Pattern (비지터 패턴)
개념:
객체 구조를 순회하며, 각 객체에 대한 연산을 정의할 수 있는 패턴.
구조 다이어그램:
+---------+
| Visitor |
+---------+
|
+---------+
| Element |
+---------+
|
+----------+----------+
| |
+---------+ +---------+
| Concrete | | Concrete |
| ElementA | | ElementB |
+---------+ +---------+
예제 코드:
interface Visitor {
void visit(Book book);
void visit(DVD dvd);
}
interface Item {
void accept(Visitor visitor);
}
class Book implements Item {
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
class DVD implements Item {
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
class DiscountVisitor implements Visitor {
public void visit(Book book) {
System.out.println("Book Discount Applied.");
}
public void visit(DVD dvd) {
System.out.println("DVD Discount Applied.");
}
}
public class Main {
public static void main(String[] args) {
Item book = new Book();
Item dvd = new DVD();
Visitor discountVisitor = new DiscountVisitor();
book.accept(discountVisitor);
dvd.accept(discountVisitor);
}
}
출력:
Book Discount Applied.
DVD Discount Applied.
장단점:
장점: 객체 구조를 변경하지 않고 새로운 기능을 추가할 수 있음
단점: 객체 구조가 자주 변경될 경우, 방문자 클래스도 함께 수정해야 함
---
'Learning > .programming' 카테고리의 다른 글
[디자인 패턴] 2) 구조 패턴 (0) | 2025.05.18 |
---|---|
[디자인 패턴] 4) 추가 패턴 (0) | 2025.05.18 |
[디자인 패턴] 1) 생성 패턴 (0) | 2025.05.18 |
[오토핫키 AutoHotKey] 컴퓨터 켤 때 자동 실행시키기 (0) | 2022.09.12 |
[오토핫키 AutoHotKey] 방향키 리맵핑 스크립트 (Alt, CapsLock) (0) | 2022.09.12 |
[오토핫키 AutoHotKey] 설치 & Script 파일 만들기 (0) | 2022.09.12 |
[오토핫키 AutoHotKey] 방향키 리맵핑하기 (Alt, CapsLock) (0) | 2022.09.12 |
[AWS 프리티어 종료 후 과금] 인스턴스 종료, 환불문의, 계정탈퇴 (0) | 2022.04.03 |