디자인패턴에 입문했다.
디자인패턴은 여러가지 설계 유형의 존재 이유와 효용을 공부하는 것이다.
이를 통해 코드의 재사용성과 유연성, 확장성을 확보할 수 있게 된다.
그리고 이미 존재하는 코드를 분석할 때에도 더 쉽게 읽어낼 수 있게 되고
다른 개발자들과 소통할때도 빠르고 간결하고 정확하게 의사소통할 수 있게 된다.
회사에서 치르는 역량 평가시험에서 설계 능력을 강하게 요구하고 있다는 것을 알 수 있었고
Okky에서 읽기에도 디자인패턴을 학습해야만 Java 개발자로서 한 단계 도약할 수 있다고 판단했다.
Classic은 당연히 GoF 디자인 패턴과 헤드퍼스트 디자인 패턴인데,
입문용으로는 헤드퍼스트가 더 추천되기에 이로 시작했다.
그리고 현재까진 이 선택에 대해 아주 만족중이다.
Joe의 SimUDuck App 개발 이야기를 통해 현재까지 배운 설계 원칙을 요약하면 다음과 같다.
1. 변화하는 부분과 변화하지 않는 부분을 분리하라.
2. 상속 보다는 결합을 선호하라.
상속은 여러 문제점이 있고 재사용성은 다른 방법으로도 취할 수 있다.
반면 결합은 캡슐화, runtime에 수정 등 장점이 있다.
SimUDuck에 전략 패턴을 적용한 ClassDiagram
배운 내용을 이해하고 있는지 확인하기 위해 코드로 작성하고 클래스다이어그램을 만들어봤다.
울기와 날기 행위 인터페이스가 있고 이를 상속한 클래스들이 있다.
어떤 식으로 우는지, 어떤 식으로 나는지 상세 내용을 정의한 클래스들이 인터페이스를 상속한다.
Duck 슈퍼클래스에선 울기와 날기 행위 인터페이스를 필드로 가지고 있다.
또한 각각의 인터페이스에 대한 setter 메소드를 가지고 있다.
그리고 각각의 인터페이스의 행위를 실행하는 울기, 날기 메소드가 있다.
그리고 각각의 오리 개체 클래스들은 Duck 슈퍼클래스를 상속한다.
runtime에 수행하고자 하는 행위를 Duck 슈퍼클래스로부터 상속받은 setter로 연결해준다.
이로서 코드의 재사용성, 유연성과 확장성을 확보했고, runtime에 행위 수정이 가능해졌다.
회사에서 개발건을 진행하며 코드의 중복이 발생하는데 어떻게 이를 해결해야할지 거의 하루를 골머리를 앓았는데,
사수분께서 5분만에 뚝딱 완벽하게 리팩토링해내는 모습을 보고 경악을 금할 수 없었다.
추상클래스로 공통부를 모두 빼내고, 공통부 내에서 일부 바뀌는 부분을 추상메소드로 선언한 다음,
추상 메소드를 공통부에서 수행하게 만든다.
그리고 추상 메소드는 각각의 행위 패턴에서 재정의한다.
가 내가 이해한 당시의 리팩토링의 과정이다.
정말 객체지향에 대해서 난 1도 모르는구나 라고 느끼면서,
동시에 진짜 객체지향을 공부하기 시작한걸까 하는 기대감도 든다.
혹시 코드로 보고 싶어하는 분이 계실까 싶어 코드를 추가한다.
public interface QuackBehavior {
void quack();
}
public class QuackVeryLoud implements QuackBehavior{
@Override
public void quack() {
System.out.println("I can quack very loudly!");
}
}
public class QuackWithSilence implements QuackBehavior{
@Override
public void quack() {
System.out.println("I can not make any sound!");
}
}
public interface FlyBehavior {
void fly();
}
public class FlyWithRocket implements FlyBehavior{
@Override
public void fly() {
System.out.println("I'm flying like a Rocket!");
}
}
public class FlyWithWings implements FlyBehavior{
@Override
public void fly() {
System.out.println("I'm flying with wings!");
}
}
abstract class Duck {
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public void setFlyBehavior(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}
public void setQuackBehavior(QuackBehavior quackBehavior) {
this.quackBehavior = quackBehavior;
}
public void quack() {
quackBehavior.quack();
}
public void fly() {
flyBehavior.fly();
}
}
public class MallardDuck extends Duck{}
public class ElectricDuck extends Duck{}
public class ToyDuck extends Duck{}
public class Main {
public static void main(String[] args){
Duck mallardDuck = new MallardDuck();
mallardDuck.setFlyBehavior(new FlyWithWings());
mallardDuck.fly();
mallardDuck.setFlyBehavior(new FlyWithRocket());
mallardDuck.fly();
mallardDuck.setQuackBehavior(new QuackVeryLoud());
mallardDuck.quack();
mallardDuck.setQuackBehavior(new QuackWithSilence());
mallardDuck.quack();
}
}
'Java & Spring' 카테고리의 다른 글
SpringBoot에서 오라클 클라우드 Autonomous Databases 접속하기 (10) | 2021.05.19 |
---|---|
Google OTP 인증 Java로 구현하기 (2) | 2021.01.24 |
Spring MVC 프로퍼티 파일 value 가져오기 (0) | 2020.09.29 |
Spring MVC 멀티 파일 업로드 (0) | 2020.09.29 |
스프링 크롤링+스케쥴링 (0) | 2020.08.10 |