상태패턴 2부 패턴적용하기

2022-07-29-상태패턴-2부-패턴적용하기

목차

01.패턴 적용해보기

01.1 Client

01.2 Student

01.3 OnlineCourse

01.4 state

02.concreate state

02.1 Draft

02.2 Private

02.3 Published

01.패턴 적용해보기

01.1 Client

  • before

    package me.whiteship.designpatterns._03_behavioral_patterns._20_state._01_before;
    
    public class Client {
    
      public static void main(String[] args) {
          Student student = new Student("whiteship");
          OnlineCourse onlineCourse = new OnlineCourse();
    
          Student keesun = new Student("keesun");
          keesun.addPrivateCourse(onlineCourse);
    
          onlineCourse.addStudent(student);
          onlineCourse.changeState(OnlineCourse.State.PRIVATE);
    
          onlineCourse.addStudent(keesun);
    
          onlineCourse.addReview("hello", student);
    
          System.out.println(onlineCourse.getState());
          System.out.println(onlineCourse.getStudents());
          System.out.println(onlineCourse.getReviews());
      }
    }
  • after

    package me.whiteship.designpatterns._03_behavioral_patterns._20_state._02_after;
    
    public class Client {
    
      public static void main(String[] args) {
          OnlineCourse onlineCourse = new OnlineCourse();
          Student student = new Student("whiteship");
          Student keesun = new Student("keesun");
          keesun.addPrivate(onlineCourse);
    
          onlineCourse.addStudent(student);
    
          onlineCourse.changeState(new Private(onlineCourse));
    
          onlineCourse.addReview("hello", student);
    
          onlineCourse.addStudent(keesun);
    
          System.out.println(onlineCourse.getState());
          System.out.println(onlineCourse.getReviews());
          System.out.println(onlineCourse.getStudents());
      }
    }

01.2 Student

  • before

    package me.whiteship.designpatterns._03_behavioral_patterns._20_state._01_before;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class Student {
    
      private String name;
    
      public Student(String name) {
          this.name = name;
      }
    
      private List<OnlineCourse> privateCourses = new ArrayList<>();
    
      public boolean isEnabledForPrivateClass(OnlineCourse onlineCourse) {
          return privateCourses.contains(onlineCourse);
      }
    
      public void addPrivateCourse(OnlineCourse onlineCourse) {
          this.privateCourses.add(onlineCourse);
      }
    
      @Override
      public String toString() {
          return "Student{" +
                  "name='" + name + '\'' +
                  '}';
      }
    }
  • after

    package me.whiteship.designpatterns._03_behavioral_patterns._20_state._02_after;
    
    import java.util.HashSet;
    import java.util.Set;
    
    public class Student {
    
      private String name;
    
      public Student(String name) {
          this.name = name;
      }
    
      private Set<OnlineCourse> onlineCourses = new HashSet<>();
    
      public boolean isAvailable(OnlineCourse onlineCourse) {
          return onlineCourses.contains(onlineCourse);
      }
    
      public void addPrivate(OnlineCourse onlineCourse) {
          this.onlineCourses.add(onlineCourse);
      }
    
      @Override
      public String toString() {
          return "Student{" +
                  "name='" + name + '\'' +
                  '}';
      }
    }

01.3 OnlineCourse

  • before

    package me.whiteship.designpatterns._03_behavioral_patterns._20_state._01_before;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class OnlineCourse {
    
      public enum State {
          DRAFT, PUBLISHED, PRIVATE
      }
    
      private State state = State.DRAFT;
    
      private List<String> reviews = new ArrayList<>();
    
      private List<Student> students = new ArrayList<>();
    
      public void addReview(String review, Student student) {
          if (this.state == State.PUBLISHED) {
              this.reviews.add(review);
          } else if (this.state == State.PRIVATE && this.students.contains(student)) {
              this.reviews.add(review);
          } else {
              throw new UnsupportedOperationException("리뷰를 작성할 수 없습니다.");
          }
      }
    
      public void addStudent(Student student) {
          if (this.state == State.DRAFT || this.state == State.PUBLISHED) {
              this.students.add(student);
          } else if (this.state == State.PRIVATE && availableTo(student)) {
              this.students.add(student);
          } else {
              throw new UnsupportedOperationException("학생을 해당 수업에 추가할 수 없습니다.");
          }
    
          if (this.students.size() > 1) {
              this.state = State.PRIVATE;
          }
      }
    
      public void changeState(State newState) {
          this.state = newState;
      }
    
      public State getState() {
          return state;
      }
    
      public List<String> getReviews() {
          return reviews;
      }
    
      public List<Student> getStudents() {
          return students;
      }
    
      private boolean availableTo(Student student) {
          return student.isEnabledForPrivateClass(this);
      }
    
    
    }
  • after

    package me.whiteship.designpatterns._03_behavioral_patterns._20_state._02_after;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class OnlineCourse {
    
      private State state = new Draft(this);
    
      private List<Student> students = new ArrayList<>();
    
      private List<String> reviews = new ArrayList<>();
    
      public void addStudent(Student student) {
          this.state.addStudent(student);
      }
    
      public void addReview(String review, Student student) {
          this.state.addReview(review, student);
      }
    
      public State getState() {
          return state;
      }
    
      public List<Student> getStudents() {
          return students;
      }
    
      public List<String> getReviews() {
          return reviews;
      }
    
      public void changeState(State state) {
          this.state = state;
      }
    }

01.4 state

package me.whiteship.designpatterns._03_behavioral_patterns._20_state._02_after;

public interface State {

    void addReview(String review, Student student);

    void addStudent(Student student);
}

02.concreate state

02.1 Draft

package me.whiteship.designpatterns._03_behavioral_patterns._20_state._02_after;

public class Draft implements State {

    private OnlineCourse onlineCourse;

    public Draft(OnlineCourse onlineCourse) {
        this.onlineCourse = onlineCourse;
    }

    @Override
    public void addReview(String review, Student student) {
        throw new UnsupportedOperationException("드래프트 상태에서는 리뷰를 남길 수 없습니다.");
    }

    @Override
    public void addStudent(Student student) {
        this.onlineCourse.getStudents().add(student);
        if (this.onlineCourse.getStudents().size() > 1) {
            this.onlineCourse.changeState(new Private(this.onlineCourse));
        }
    }
}

02.2 Private

package me.whiteship.designpatterns._03_behavioral_patterns._20_state._02_after;

public class Private implements State {

    private OnlineCourse onlineCourse;

    public Private(OnlineCourse onlineCourse) {
        this.onlineCourse = onlineCourse;
    }

    @Override
    public void addReview(String review, Student student) {
        if (this.onlineCourse.getStudents().contains(student)) {
            this.onlineCourse.getReviews().add(review);
        } else {
            throw new UnsupportedOperationException("프라이빗 코스를 수강하는 학생만 리뷰를 남길 수 있습니다.");
        }
    }

    @Override
    public void addStudent(Student student) {
        if (student.isAvailable(this.onlineCourse)) {
            this.onlineCourse.getStudents().add(student);
        } else {
            throw new UnsupportedOperationException("프라이빗 코스를 수강할 수 없습니다.");
        }
    }
}
  • this.onlineCourse.getStudents().contains(student)

    • 이렇게 3개 이상있으면 냄새라고 하는데 원래는 두개정도되게 리팩토링하는게 좋다.

02.3 Published

package me.whiteship.designpatterns._03_behavioral_patterns._20_state._02_after;

public class Published implements State {

    private OnlineCourse onlineCourse;

    public Published(OnlineCourse onlineCourse) {
        this.onlineCourse = onlineCourse;
    }

    @Override
    public void addReview(String review, Student student) {
        this.onlineCourse.getReviews().add(review);
    }

    @Override
    public void addStudent(Student student) {
        this.onlineCourse.getStudents().add(student);
    }
}
  • 위에처럼 해놓으면 이해하기가 좀더 수월해졌음

    • 하지만 클래스가 많아지긴하지만 그래도 많이 개선됨

Written by@[KyeongMinPark]
Docker, C++, C#, Java, Golang으로 개발 모니터링운영 및 개발, 자원수집기 Beat & Exporter 개발 Gitlab Runner CI/CD & Hugo 연동과 테스트코드및 등을 공부와 개발중 ORM, TDD, BDD, DDD, DesignPattern, WebAssembly Studying

GitHub