디자인 모델 -- Builder 모델 에 대한 사고

7650 단어
일상적인 개발 에서 항상 다 중 매개 변수 상황 을 만 날 수 있다. 그러면 다 중 매개 변수, 특히 선택 할 수 있 는 매개 변수 가 많은 상황 에 대해 다음 과 같은 해결 방안 이 있 을 수 있다.
중첩 구조 기 모드
중첩 구조 기 모드 는 자바 코드 에서 흔히 볼 수 있 습 니 다. 그 해결 문 제 는 매개 변수 가 너무 많은 상황 에서 호출 자 에 게 너무 많은 실례 화 대상 부담 을 주 고 싶 지 않 습 니 다. 이런 상황 에서 호출 자 는 자신 에 게 적합 한 구조 함수 호출 만 선택 하면 됩 니 다.
  public Configuration(Integer maxConnect) {
    this(maxConnect, 0);
  }

  public Configuration(Integer maxConnect, Integer minConnect) {
    this("default", maxConnect, minConnect);
  }

  public Configuration(String password, Integer maxConnect, Integer minConnect) {
    this(...)
  }

그러나 사실은 사람 이 원 하 는 대로 되 지 않 는 다. 이 모델 은 단점 이 많다.
  • 층 층 이 삽입 되 어 전체 실례 화 과정 은 사실 하나의 직선 이 고 끝까지 연결 되면 그 과정 이 유연 하지 못 하도록 정 해 져 있다.
  • 매개 변수 가 비교적 적은 구조 함수 에 대해 기본 값 을 채 워 야 하기 때문에 우아 해 보이 지 않 습 니 다.
  • 파 라 메 터 를 증가 하 는 것 은 이런 모델 에 있어 어려움 이 많 고 바닥 에서 윗 층 까지 수정 해 야 한다.
  • 공장 모드
    공장 모델 은 구체 적 인 창설 절 차 를 봉인 하고 간단 하고 편리 한 입 구 를 제공 하 는 데 목적 을 둔다. 그러나 다 중 파라미터 상황 에서 개선 할 수 있 는 것 은 실례 화 과정 이 더 이상 직선 이 아니 라 공장 에서 구체 적 인 파라미터 에 따라 Configuration 와 그 자 류 를 제조 할 수 있다. 그 본질 과 중첩 구조 모델 은 큰 차이 가 없다. 다만 구조 기 논 리 를 해당 공장 에 추출 할 뿐이다.그래서 공장 모델 은 이런 문 제 를 해결 할 수 없다.
     public static Configuration newInstance(String password) {
        return new Configuration("default", password, "default");
      }
    
      public static Configuration newInstance(String password, String username) {
        return new Configuration(username, password, "default");
      }
    
      public static Configuration newInstance(String password, String username, String url,) {
        return new Configuration(username, password, url);
      }
    

    JavaBean 모드
    엄격 한 자바 빈 은 빈 구조 함수 만 있 고 다른 속성 은 set 방법 을 일률적으로 사용 합 니 다. 물론 필요 한 매개 변 수 는 구조 함수 에 넣 을 수 있 습 니 다. 그러면 아래 의 이런 형식 이 됩 니 다.
        Configuration configuration = new Configuration();
        configuration.setPassword("default");
        configuration.setUrl("http://mrdear.cn");
        configuration.setUsername("default");
    

    지루 한 매개 변수 목록 이 줄 어 들 었 지만 단점 도 뚜렷 하 다.
  • 대상 의 생 성 과정 이 분해 되 었 습 니 다. 의도 에 따라 new 의 과정 은 생 성 입 니 다. 나머지 는 모두 생 성 되 지 않 습 니 다. 그러나 이런 모델 에서 의 생 성 은 실제 적 으로 두 단계 이 고 생 성 과 작성 값 입 니 다.
  • 수정 에 개방 되 었 습 니 다. 이 모델 은 너무 많은 set 방법 을 노출 하여 이 인 스 턴 스 를 얻 을 수 있 는 곳 에서 마음대로 기 내용 을 수정 할 수 있 습 니 다. 전체적인 config 인 스 턴 스 나 다른 단일 인 스 턴 스 에 치 명 적 인 단점 입 니 다.
  • 빌 더 모드
    잘 한 말 이 있 습 니 다. 해결 하기 어 려 운 문제 에 부 딪 히 면 중간 층 을 더 해서 추상 을 대리 합 니 다. Builder 모델 이 정식 적 으로 이와 같 습 니 다. 대상 자체 가 번 거 로 움 을 만 들 면 하나의 대리 대상 을 사용 하여 생 성과 검 사 를 주도 하고 중첩 기 모델 의 안전성 과 자바 빈 모델 의 유연성 을 동시에 고려 합 니 다.
    public class Configuration {
      private String username;
      private String password;
      private String url;
    
      public Configuration(String username, String password, String url) {
        this.username = username;
        this.password = password;
        this.url = url;
      }
    
      public static ConfigurationBuilder builder() {
        return new ConfigurationBuilder();
      }
    
      public static class ConfigurationBuilder {
        private String username;
        private String password;
        private String url;
    
        ConfigurationBuilder() {
        }
    
        public ConfigurationBuilder username(String username) {
          this.username = username;
          return this;
        }
    
        public ConfigurationBuilder password(String password) {
          this.password = password;
          return this;
        }
    
        public ConfigurationBuilder url(String url) {
          this.url = url;
          return this;
        }
    
        public Configuration build() {
          // can some check
          return new Configuration(this.username, this.password, this.url);
        }
    
        public String toString() {
          return new StringBuilder().append((String)"Configuration.ConfigurationBuilder(username=").append((String)this.username).append((String)", password=").append((String)this.password).append((String)", url=").append((String)this.url).append((String)")").toString();
        }
      }
    }
    

    위의 코드 와 같이 클 라 이언 트 는 Builder 대상 을 사용 하여 필요 한 인 자 를 선택 한 다음 에 마지막 으로 build () 는 자신 이 원 하 는 인 자 를 구축 합 니 다. Builder 는 많은 장점 을 가지 고 유연 합 니 다.
  • 선형 구조 용 build 방법 을 분기 구조 로 바 꾸 었 습 니 다. build 구조 와 같은 하위 클래스 와 다른 관련 류 를 사용 할 수 있 습 니 다.
  • 유연 하고 조합의 형식 은 각자 builder 에서 제약 검 사 를 강화 할 수 있 으 며 이러한 업무 논 리 는 당신 의 원 류 를 오염 시 키 지 않 습 니 다. 부합 되 지 않 는 매개 변 수 는 제때에 던 져 야 합 니 다 IllegalArgumentException
  • 매개 변수 로 전달 할 수 있 습 니 다. 예 를 들 어 Mybatis 에서 이런 전달 방식 을 대량으로 사용 하여 클 라 이언 트 를 더욱 편리 하 게 하 는 구조 설정 류 입 니 다.
  • .filed() 형식 으로 파 라 메 터 를 구축 합 니 다. 이름 이 일정한 규범 이 있 으 면 매개 변수의 역할 을 잘 알 고 작 성 된 코드 도 쉽게 읽 을 수 있 습 니 다. 구체 적 인 파 라 메 터 를 클릭 하지 않 아 도 자신 에 게 맞 는 방법 을 선택 할 수 있 습 니 다.
  • 물론 단점 도 있다.
  • 원 하 는 종 류 를 만 들 기 전에 builder 중간 류 를 만들어 야 합 니 다. 자주 순환 하 는 실례 화 된 종 류 는 적합 하지 않 습 니 다. 대량의 대상 이 중복 되 어 만 들 면 성능 에 영향 을 줄 수 있 습 니 다. 따라서 복잡 한 설정 류 에 builder 를 사용 할 때 가장 적합 합 니 다.
  • Mybatis 에서 Builder 모드 적용
    Mybatis 는 다양한 설정 을 가지 고 있 습 니 다. builder 는 설정 대상 에 적합 합 니 다. MappedStatement 클래스 를 예 로 들 면 수 십 개의 설정 을 가지 고 있 습 니 다. 구조 함수 나 정적 공장 을 사용 하면 개발 자 들 이 받 아들 이기 어 려 운 체험 이 될 수 있 습 니 다. 많은 매개 변 수 를 입력 해 야 모든 매개 변수의 의 미 를 알 수 있 습 니 다.이런 상황 에서 Builder 모드 는 좋 은 해결 방법 입 니 다.
    public final class MappedStatement {
    
      private String resource;
      private Configuration configuration;
      private String id;
      private Integer fetchSize;
      private Integer timeout;
      private StatementType statementType;
      private ResultSetType resultSetType;
      private SqlSource sqlSource;
        ......
    }
    
    MappedStatementorg.apache.ibatis.mapping.MappedStatement.Builder 의 정적 내부 클래스 로 서 MappedStatement 임 의 속성 에 접근 할 수 있 는 권 리 를 가진다. 그러면 대상 을 직접 예화 MappedStatement 한 다음 에 이 대상 을 사용 하여 속성 에 직접 접근 하여 Builder 모드 를 간소화 하고 mappedStatement 의 인 스 턴 스 를 만 들 수 있다.
      public static class Builder {
        private MappedStatement mappedStatement = new MappedStatement();
    
        public Builder(Configuration configuration, String id, SqlSource sqlSource, SqlCommandType sqlCommandType) {
          mappedStatement.configuration = configuration;
          mappedStatement.id = id;
          mappedStatement.sqlSource = sqlSource;
          mappedStatement.statementType = StatementType.PREPARED;
          mappedStatement.parameterMap = new ParameterMap.Builder(configuration, "defaultParameterMap", null, new ArrayList()).build();
          mappedStatement.resultMaps = new ArrayList();
          mappedStatement.sqlCommandType = sqlCommandType;
          mappedStatement.keyGenerator = configuration.isUseGeneratedKeys() && SqlCommandType.INSERT.equals(sqlCommandType) ? Jdbc3KeyGenerator.INSTANCE : NoKeyGenerator.INSTANCE;
          String logId = id;
          if (configuration.getLogPrefix() != null) {
            logId = configuration.getLogPrefix() + id;
          }
          mappedStatement.statementLog = LogFactory.getLog(logId);
          mappedStatement.lang = configuration.getDefaultScriptingLanguageInstance();
        }
    
        public Builder resource(String resource) {
          mappedStatement.resource = resource;
          return this;
        }
        ......
    }
    

    또한 MappedStatement 대상 을 확보 하기 위해 서 는 Builder 를 사용 하여 제어 해 야 합 니 다. 코드 에서 구조 함 수 를 패키지 등급 권한 으로 설명 합 니 다.
      MappedStatement() {
        // constructor disabled
      }
    

    총결산
    Builder 모델 은 본질 적 으로 특수 한 공장 모델 로 라인 방식 에 따라 호출 한 다음 에 마지막 으로 제품 의 합격 여 부 를 검사 하고 라인 간 에 임 의적 으로 조합 하여 고도 의 유연성 을 이 룰 수 있다.
    레 퍼 런 스
    Effective Java: 여러 구조 기 파 라 메 터 를 만 났 을 때 구축 기 (Builder 모드) 를 고려 합 니 다.

    좋은 웹페이지 즐겨찾기