행위 패턴(Behavioral Patterns)은 객체나 클래스 사이의 상호작용과 책임 분배를 다루는 디자인 패턴으로, 시스템의 복잡한 흐름을 관리합니다. 행위 패턴은 알고리즘, 책임 할당, 객체 간의 통신을 쉽게 구현할 수 있게 해줍니다. 아래에서는 주요 행위 패턴들을 상세히 분석하겠습니다.
import java.util.ArrayList;
import java.util.List;
interface Observer {
void update(String state);
}
class ConcreteObserver implements Observer {
private String observerState;
public void update(String state) {
observerState = state;
System.out.println("Observer state updated to: " + observerState);
}
}
class Subject {
private List<Observer> observers = new ArrayList<>();
private String state;
public void attach(Observer observer) {
observers.add(observer);
}
public void detach(Observer observer) {
observers.remove(observer);
}
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(state);
}
}
public void setState(String state) {
this.state = state;
notifyObservers();
}
}
interface State {
void handle(Context context);
}
class ConcreteStateA implements State {
public void handle(Context context) {
System.out.println("State A handling request.");
context.setState(new ConcreteStateB());
}
}
class ConcreteStateB implements State {
public void handle(Context context) {
System.out.println("State B handling request.");
context.setState(new ConcreteStateA());
}
}
class Context {
private State state;
public Context(State state) {
this.state = state;
}
public void setState(State state) {
this.state = state;
}
public void request() {
state.handle(this);
}
}
interface Strategy {
void execute();
}
class ConcreteStrategyA implements Strategy {
public void execute() {
System.out.println("Executing strategy A");
}
}
class ConcreteStrategyB implements Strategy {
public void execute() {
System.out.println("Executing strategy B");
}
}
class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
public void executeStrategy() {
strategy.execute();
}
}
abstract class AbstractClass {
public final void templateMethod() {
primitiveOperation1();
primitiveOperation2();
concreteOperation();
}
protected abstract void primitiveOperation1();
protected abstract void primitiveOperation2();
private void concreteOperation() {
System.out.println("Concrete operation");
}
}
class ConcreteClass extends AbstractClass {
protected void primitiveOperation1() {
System.out.println("Primitive operation 1");
}
protected void primitiveOperation2() {
System.out.println("Primitive operation 2");
}
}
interface Command {
void execute();
}
class ConcreteCommand implements Command {
private Receiver receiver;
public ConcreteCommand(Receiver receiver) {
this.receiver = receiver;
}
public void execute() {
receiver.action();
}
}
class Receiver {
public void action() {
System.out.println("Receiver action executed");
}
}
class Invoker {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void executeCommand() {
command.execute();
}
}
import java.util.ArrayList;
import java.util.List;
interface Iterator<T> {
boolean hasNext();
T next();
}
class ConcreteIterator<T> implements Iterator<T> {
private List<T> collection;
private int position = 0;
public ConcreteIterator(List<T> collection) {
this.collection = collection;
}
public boolean hasNext() {
return position < collection.size();
}
public T next() {
if (this.hasNext()) {
return collection.get(position++);
}
return null;
}
}
interface Aggregate<T> {
Iterator<T> createIterator();
}
class ConcreteAggregate<T> implements Aggregate<T> {
private List<T> collection = new ArrayList<>();
public void add(T item) {
collection.add(item);
}
public Iterator<T> createIterator() {
return new ConcreteIterator<>(collection);
}
}
interface Mediator {
void notify(Object sender, String event);
}
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 notify(Object sender, String event) {
if (event.equals("A")) {
colleague2.doSomething();
} else if (event.equals("B")) {
colleague1.doSomething();
}
}
}
class Colleague {
protected Mediator mediator;
public Colleague(Mediator mediator) {
this.mediator = mediator;
}
}
class ConcreteColleague1 extends Colleague {
public ConcreteColleague1(Mediator mediator) {
super(mediator);
}
public void doSomething() {
System.out.println("ConcreteColleague1 does something");
}
public void triggerEvent() {
mediator.notify(this, "A");
}
}
class ConcreteColleague2 extends Colleague {
public ConcreteColleague2(Mediator mediator) {
super(mediator);
}
public void doSomething() {
System.out.println("ConcreteColleague2 does something");
}
public void triggerEvent() {
mediator.notify(this, "B");
}
}
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 String getState() {
return state;
}
public Memento saveStateToMemento() {
return new Memento(state);
}
public void getStateFromMemento(Memento memento) {
state = memento.getState();
}
}
class Caretaker {
private List<Memento> mementoList = new ArrayList<>();
public void add(Memento state) {
mementoList.add(state);
}
public Memento get(int index) {
return mementoList.get(index);
}
}
abstract class Handler {
protected Handler nextHandler;
public void setNextHandler(Handler nextHandler) {
this.nextHandler = nextHandler;
}
public abstract void handleRequest(String request);
}
class ConcreteHandler1 extends Handler {
public void handleRequest(String request) {
if (request.equals("Request1")) {
System.out.println("ConcreteHandler1 handled request");
} else if (nextHandler != null) {
nextHandler.handleRequest(request);
}
}
}
class ConcreteHandler2 extends Handler {
public void handleRequest(String request) {
if (request.equals("Request2")) {
System.out.println("ConcreteHandler2 handled request");
} else if (nextHandler != null) {
nextHandler.handleRequest(request);
}
}
}
interface Visitor {
void visit(ConcreteElementA element);
void visit(ConcreteElementB element);
}
class ConcreteVisitor implements Visitor {
public void visit(ConcreteElementA element) {
System.out.println("Visiting ConcreteElementA");
}
public void visit(ConcreteElementB element) {
System.out.println("Visiting ConcreteElementB");
}
}
interface Element {
void accept(Visitor visitor);
}
class ConcreteElementA implements Element {
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
class ConcreteElementB implements Element {
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
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);
}
}
class OrExpression implements Expression {
private Expression expr1;
private Expression expr2;
public OrExpression(Expression expr1, Expression expr2) {
this.expr1 = expr1;
this.expr2 = expr2;
}
public boolean interpret(String context) {
return expr1.interpret(context) || expr2.interpret(context);
}
}
class AndExpression implements Expression {
private Expression expr1;
private Expression expr2;
public AndExpression(Expression expr1, Expression expr2) {
this.expr1 = expr1;
this.expr2 = expr2;
}
public boolean interpret(String context) {
return expr1.interpret(context) && expr2.interpret(context);
}
}
활용 예시: SQL 파서, 정규 표현식 해석기행위 패턴은 객체 간의 상호작용을 효율적으로 관리하고, 코드의 유연성과 재사용성을 높이는 데 중요한 역할을 합니다. 각 패턴을 적절히 활용하여 시스템의 복잡성을 관리하고 유지 보수성을 향상시키는 것이 중요합니다.