안녕하세요, 코린이의 코딩 학습기 채니 입니다.
개인 포스팅용으로 내용에 오류 및 잘못된 정보가 있을 수 있습니다.
전략패턴 (Strategy Pattern)
- GoF의 디자인 패턴에 소개된 행위 패턴 중 하나
만일 철수가 강아지를 키우고, 영희가 고양이를 키운다고 하였을 때, Person클래스가 존재하고 주인 이름 / 펫 종류를 필드로 갖게 될 것 입니다.
각 반려동물에 맞는 Dog 클래스와 Cat 클래스가 존재할 것이고, Person 클래스의 필드로 자리잡게 되겠죠.
그렇다면 Person has a Dog / Person has a Cat → 즉 Person은 Cat, Dog에 의존하게 됩니다.
만일 강아지만 키운다고 하였을 때, Cat 클래스는 null이 될 것이고 Snake를 키우는 맹구가 등장한다면 Person클래스에 Snake필드를 추가해줘야할 것이고, 이는 비효율적입니다.
Pet클래스(추상클래스 혹은 인터페이스)를 하나 생성하여 각각의 Dog, Cat, ...이 Pet클래스를 상속받는다면 효율적으로 관리할 수 있을겁니다.
Person
public class Person {
private String name; // 주인이름
private Pet pet;
public Person() {
super();
// TODO Auto-generated constructor stub
}
public Person(String name, Pet pet) {
super();
this.name = name;
this.pet = pet;
}
// getter, setter 생략
@Override
public String toString() {
return "Person [name=" + name + ", pet=" + pet + "]";
}
}
Pet
public abstract class Pet {
protected String name; // 반려동물 이름
public Pet() {
super();
// TODO Auto-generated constructor stub
}
public Pet(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Dog
public class Dog extends Pet {
public Dog() {
super();
// TODO Auto-generated constructor stub
}
public Dog(String name) {
super(name);
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "Dog [name=" + name + "]";
}
}
Cat
public class Cat extends Pet {
public Cat() {
super();
// TODO Auto-generated constructor stub
}
public Cat(String name) {
super(name);
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "Cat [name=" + name + "]";
}
}
- Dog, Cat 클래스는 Pet클래스를 상속하므로, String name 필드가 포함되어있으며 생성자는 상속이 불가하여 선언해줌!
Main
public class Main {
public static void main(String[] args) {
Person p1 = new Person("철수", new Dog("구리구리"));
Person p2 = new Person("영희", new Cat("두리두리"));
System.out.println(p1);
System.out.println(p2);
}
}
@콘솔출력값
Person [name=철수, pet=Dog [name=구리구리]]
Person [name=영희, pet=Cat [name=두리두리]]
이처럼, 이 외 클래스들이 추가되어도 Person 클래스를 수정할 필요 없이 Pet클래스를 상속받아 사용하면 됩니다.
Context
- Person
- Strategy를 이용하는 클래스
- 필요에 따라 구체적인 전략 (Dog, Cat)을 바꿔서 사용할 수 있어야 함 (직접 의존하고 있다면, Person클래스가 같이 수정되어야함)
Strategy
- Pet
- 인터페이스/추상클래스
- Context가 의존하는 타입으로 자식 클래스에 대해 동일한 규격 제공
Concrete Strategy
- Dog/Cat
- Strategy 클래스의 구현체
- Strategy를 수행하는 주체
Snake 반려동물 추가
Snake
public class Snake extends Pet {
public Snake() {
super();
// TODO Auto-generated constructor stub
}
public Snake(String name) {
super(name);
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "Snake [name=" + name + "]";
}
}
Main
public class Main {
public static void main(String[] args) {
Person p1 = new Person("철수", new Dog("구리구리"));
Person p2 = new Person("영희", new Cat("두리두리"));
System.out.println(p1);
System.out.println(p2);
// Person이 가질 수 있는 반려동물 Class 이후에 추가될 수 있음
Person p3 = new Person("맹구", new Snake("쉬리릭"));
System.out.println(p3);
}
}
@콘솔출력값
Person [name=맹구, pet=Snake [name=쉬리릭]]
이렇듯, Context가 구체적인 전략에 의존하지 않고 전략 클래스에만 의존하고 있기 때문에 Pet의 자식 타입을 200개 만들어도 Person은 변경되지 않게 됩니다.
자식클래스에서 toString() 중복 제거
Person클래스 toString()
@Override
public String toString() {
String className = this.getClass().getName();
return className.substring(className.lastIndexOf(".")+1) + " [name=" + name + "]";
}
@콘솔출력값
Person [name=철수, pet=Dog asf[name=구리구리]]
Person [name=영희, pet=Cat asf[name=두리두리]]
Person [name=맹구, pet=Snake asf[name=쉬리릭]]
'Java > Spring' 카테고리의 다른 글
Spring) 스프링 개요, 특징, 주요 모듈 (0) | 2022.08.11 |
---|---|
Spring) Emmet / Lombok 설치 및 환경설정 (0) | 2022.08.11 |
Spring) STS 다운로드 및 환경 설정 (0) | 2022.08.11 |
전략패턴) Servlet - Controller - Service - Dao 흐름 (0) | 2022.08.04 |
프레임워크) Framework란?, 프레임워크와 라이브러리의 차이점 (0) | 2022.08.02 |