1. 전략 패턴 (Strategy Pattern)
- 정의: 전략 패턴은 객체의 동작(알고리즘, 정책 등)을 캡슐화하여 교체 가능하게 만드는 디자인 패턴입니다.

- 핵심 요소:
• 특정 기능(행동)을 추상 인터페이스로 정의합니다. (예: Strategy)
• 다양한 전략(구현 클래스들)이 해당 인터페이스를 구현하여 서로 다른 동작을 제공합니다.
• 실행 중 전략을 변경할 수 있어 유연성이 높아집니다.
- 전략 패턴은 컴포지션(Composition) 방식을 활용하여 OCP(Open Closed Principle)를 준수하는 대표적인 설계 방식입니다.
2. 개방-폐쇄 원칙 (Open Closed Principle, OCP)
- 정의: 확장에는 열려 있고, 변경에는 닫혀 있어야 합니다.
- SOLID 원칙 중 O에 해당하며, 객체지향 설계의 핵심 원칙 중 하나입니다.
2.1. OCP 적용 방식
2.1.1. 상속 (Inheritance)
• is-a 관계: 한 클래스는 다른 클래스를 상속받습니다.
• 부모 클래스의 변경 없이 기능 확장이 가능하면 OCP를 준수할 수 있습니다.
• 하지만 높은 결합도를 가지며 부모 클래스를 수정할 가능성이 존재합니다.
• 단일 상속만 가능하므로 한계가 있습니다.
2.1.2. 컴포지션 (Composition)
• has-a 관계: 한 클래스는 다른 클래스의 인스턴스를 포함합니다.
• 낮은 결합도를 유지할 수 있고, 다중 컴포지션도 가능합니다.
• 대표적 예: 인터페이스 활용, 전략 패턴 사용
• 컴포지션 방식은 OCP 적용에 더 적합하며 유지보수성과 확장성을 제공합니다.
2.1.3. OCP를 위반한 코드 예제
public void printEmployeeIncen(boolean isJunior, boolean isSenior, List<Employee> employees) {
employees.sort(Comparator.comparing(Employee::getName));
double incentive;
for (Employee employee : employees) {
if (employee.isLazy()) {
incentive = employee.getSalary() * 12 * 0.03;
} else if (isJunior) {
incentive = employee.getSalary() * 12 * 0.08;
} else if (isSenior) {
incentive = employee.getSalary() * 12 * 0.15;
} else {
incentive = employee.getSalary() * 12 * 0.05;
}
System.out.println(employee.getName() + "의 인센티브는 " + incentive + "(원) 입니다.");
}
}
2.1.4. OCP를 준수한 코드: 전략 패턴 적용
@RequiredArgsConstructor
public class Calculator {
private final IncentiveStrategy incentiveStrategy;
public void printEmployeeIncen(List<Employee> employees) {
employees.sort(Comparator.comparing(Employee::getName));
for (Employee employee : employees) {
double incentive = incentiveStrategy.calculateIncentive(employee);
System.out.println(employee.getName() + "의 인센티브는 " + incentive + "(만원) 입니다.");
}
}
}
public interface IncentiveStrategy {
double calculateIncentive(Employee employee);
}
public class LazyIncentiveStrategy implements IncentiveStrategy {
public double calculateIncentive(Employee employee) {
return employee.getSalary() * 12 * 0.03;
}
}
public class InternIncentiveStrategy implements IncentiveStrategy {
public double calculateIncentive(Employee employee) {
return employee.getSalary() * 12 * 0.05;
}
}
public class JuniorIncentiveStrategy implements IncentiveStrategy {
public double calculateIncentive(Employee employee) {
return employee.getSalary() * 12 * 0.08;
}
}
public class SeniorIncentiveStrategy implements IncentiveStrategy {
public double calculateIncentive(Employee employee) {
return employee.getSalary() * 12 * 0.15;
}
}
public static void main(String[] args) {
Employee lazy = new Employee("송직원", 200, true, EmployeeLevel.INTERN);
Employee intern = new Employee("이직원", 200, false, EmployeeLevel.INTERN);
Employee junior1 = new Employee("김직원", 250, false, EmployeeLevel.JUNIOR);
Employee junior2 = new Employee("최직원", 250, false, EmployeeLevel.JUNIOR);
Employee senior1 = new Employee("신직원", 400, false, EmployeeLevel.SENIOR);
Employee senior2 = new Employee("박직원", 300, false, EmployeeLevel.SENIOR);
Calculator lazyIncen = new Calculator(new LazyIncentiveStrategy());
Calculator internIncen = new Calculator(new InternIncentiveStrategy());
Calculator juniorIncen = new Calculator(new JuniorIncentiveStrategy());
Calculator seniorIncen = new Calculator(new SeniorIncentiveStrategy());
lazyIncen.printEmployeeIncen(List.of(lazy));
internIncen.printEmployeeIncen(List.of(intern));
juniorIncen.printEmployeeIncen(List.of(junior1, junior2));
seniorIncen.printEmployeeIncen(List.of(senior1, senior2));
}
송직원의 인센티브는 72.0(원) 입니다.
이직원의 인센티브는 120.0(원) 입니다.
김직원의 인센티브는 240.0(원) 입니다.
최직원의 인센티브는 240.0(원) 입니다.
신직원의 인센티브는 720.0(원) 입니다.
박직원의 인센티브는 540.0(원) 입니다.
3. 결론
- 전략 패턴과 OCP 적용의 장점
• if-else 문으로 인한 코드 복잡도가 제거됨
• 정책이 캡슐화되어 유지보수성 및 확장성 향상
• 기존 코드를 수정하지 않고 새로운 정책을 추가 가능
- 전략 패턴과 OCP 관계
• 전략 패턴이 OCP를 도와줄 수는 있으나, 자동으로 OCP를 보장하지는 않음
• 디자인 패턴과 SOLID 원칙은 독립적이며 보완적인 관계
⭐발표자 : 이현진님
1. 전략 패턴 (Strategy Pattern)
- 정의: 전략 패턴은 객체의 동작(알고리즘, 정책 등)을 캡슐화하여 교체 가능하게 만드는 디자인 패턴입니다.
- 핵심 요소:
• 특정 기능(행동)을 추상 인터페이스로 정의합니다. (예: Strategy)
• 다양한 전략(구현 클래스들)이 해당 인터페이스를 구현하여 서로 다른 동작을 제공합니다.
• 실행 중 전략을 변경할 수 있어 유연성이 높아집니다.
- 전략 패턴은 컴포지션(Composition) 방식을 활용하여 OCP(Open Closed Principle)를 준수하는 대표적인 설계 방식입니다.
2. 개방-폐쇄 원칙 (Open Closed Principle, OCP)
- 정의: 확장에는 열려 있고, 변경에는 닫혀 있어야 합니다.
- SOLID 원칙 중 O에 해당하며, 객체지향 설계의 핵심 원칙 중 하나입니다.
2.1. OCP 적용 방식
2.1.1. 상속 (Inheritance)
• is-a 관계: 한 클래스는 다른 클래스를 상속받습니다.
• 부모 클래스의 변경 없이 기능 확장이 가능하면 OCP를 준수할 수 있습니다.
• 하지만 높은 결합도를 가지며 부모 클래스를 수정할 가능성이 존재합니다.
• 단일 상속만 가능하므로 한계가 있습니다.
2.1.2. 컴포지션 (Composition)
• has-a 관계: 한 클래스는 다른 클래스의 인스턴스를 포함합니다.
• 낮은 결합도를 유지할 수 있고, 다중 컴포지션도 가능합니다.
• 대표적 예: 인터페이스 활용, 전략 패턴 사용
• 컴포지션 방식은 OCP 적용에 더 적합하며 유지보수성과 확장성을 제공합니다.
2.1.3. OCP를 위반한 코드 예제
public void printEmployeeIncen(boolean isJunior, boolean isSenior, List<Employee> employees) {
employees.sort(Comparator.comparing(Employee::getName));
double incentive;
for (Employee employee : employees) {
if (employee.isLazy()) {
incentive = employee.getSalary() * 12 * 0.03;
} else if (isJunior) {
incentive = employee.getSalary() * 12 * 0.08;
} else if (isSenior) {
incentive = employee.getSalary() * 12 * 0.15;
} else {
incentive = employee.getSalary() * 12 * 0.05;
}
System.out.println(employee.getName() + "의 인센티브는 " + incentive + "(원) 입니다.");
}
}
2.1.4. OCP를 준수한 코드: 전략 패턴 적용
@RequiredArgsConstructor
public class Calculator {
private final IncentiveStrategy incentiveStrategy;
public void printEmployeeIncen(List<Employee> employees) {
employees.sort(Comparator.comparing(Employee::getName));
for (Employee employee : employees) {
double incentive = incentiveStrategy.calculateIncentive(employee);
System.out.println(employee.getName() + "의 인센티브는 " + incentive + "(만원) 입니다.");
}
}
}
public interface IncentiveStrategy {
double calculateIncentive(Employee employee);
}
public class LazyIncentiveStrategy implements IncentiveStrategy {
public double calculateIncentive(Employee employee) {
return employee.getSalary() * 12 * 0.03;
}
}
public class InternIncentiveStrategy implements IncentiveStrategy {
public double calculateIncentive(Employee employee) {
return employee.getSalary() * 12 * 0.05;
}
}
public class JuniorIncentiveStrategy implements IncentiveStrategy {
public double calculateIncentive(Employee employee) {
return employee.getSalary() * 12 * 0.08;
}
}
public class SeniorIncentiveStrategy implements IncentiveStrategy {
public double calculateIncentive(Employee employee) {
return employee.getSalary() * 12 * 0.15;
}
}
public static void main(String[] args) {
Employee lazy = new Employee("송직원", 200, true, EmployeeLevel.INTERN);
Employee intern = new Employee("이직원", 200, false, EmployeeLevel.INTERN);
Employee junior1 = new Employee("김직원", 250, false, EmployeeLevel.JUNIOR);
Employee junior2 = new Employee("최직원", 250, false, EmployeeLevel.JUNIOR);
Employee senior1 = new Employee("신직원", 400, false, EmployeeLevel.SENIOR);
Employee senior2 = new Employee("박직원", 300, false, EmployeeLevel.SENIOR);
Calculator lazyIncen = new Calculator(new LazyIncentiveStrategy());
Calculator internIncen = new Calculator(new InternIncentiveStrategy());
Calculator juniorIncen = new Calculator(new JuniorIncentiveStrategy());
Calculator seniorIncen = new Calculator(new SeniorIncentiveStrategy());
lazyIncen.printEmployeeIncen(List.of(lazy));
internIncen.printEmployeeIncen(List.of(intern));
juniorIncen.printEmployeeIncen(List.of(junior1, junior2));
seniorIncen.printEmployeeIncen(List.of(senior1, senior2));
}
송직원의 인센티브는 72.0(원) 입니다.
이직원의 인센티브는 120.0(원) 입니다.
김직원의 인센티브는 240.0(원) 입니다.
최직원의 인센티브는 240.0(원) 입니다.
신직원의 인센티브는 720.0(원) 입니다.
박직원의 인센티브는 540.0(원) 입니다.
3. 결론
- 전략 패턴과 OCP 적용의 장점
• if-else 문으로 인한 코드 복잡도가 제거됨
• 정책이 캡슐화되어 유지보수성 및 확장성 향상
• 기존 코드를 수정하지 않고 새로운 정책을 추가 가능
- 전략 패턴과 OCP 관계
• 전략 패턴이 OCP를 도와줄 수는 있으나, 자동으로 OCP를 보장하지는 않음
• 디자인 패턴과 SOLID 원칙은 독립적이며 보완적인 관계
⭐발표자 : 이현진님