ENUM의 대소문자 전환 방지 – 방문자 패턴

예제를 진행하기 전에 방문자 패턴이란 무엇입니까?
다음은 Wikipedia definition 입니다.

ENUM에 대한 Switch 케이스의 일반적인 예를 들어 보겠습니다.
ENUMCountry을 고려하십시오.

public enum Country {
    CHINA,
    INDIA,
    UNITED_STATES,
    BRAZIL,
    MEXICO,
    GERMANY
}


ENUM 국가를 입력으로 사용하고 happiness score을 반환하는 함수를 작성하십시오.

public float getHappinessScore(Country country) {
    float happinessScore;
    switch (country) {
            case CHINA:
                happinessScore = 5.19;
                break;
            case INDIA:
                happinessScore = 4.01;
                break;
            case UNITED_STATES:
                happinessScore = 6.89;
                break;
            case BRAZIL:
                happinessScore = 6.30;
                break;
            case MEXICO:
                happinessScore = 6.59;
                break;
            case GERMANY:
                happinessScore = 6.98;
                break;
            default:
                // Throw an exception
        }
       return happinessScore;
}


이 점수의 정확성에 대해 걱정하지 마십시오.
자, 이 접근법의 문제점은 무엇입니까? 국가를 기반으로 조치를 취해야 하는 모든 곳에서 우리는 스위치 사례를 반복해서 작성하게 되며, 국가가 누락되지 않도록 하기 위해 개발자에게 귀속됩니다.
  • 모든 위치에서 Switch 사례가 중복되기 때문에 코드가 보기 흉해 보입니다.
  • 인적 오류 가능성이 높습니다.
  • 새 국가를 추가하는 경우 개발자는 수동으로 검색하여 모든 스위치 케이스를 업데이트해야 합니다(그러면 어떤 종류의 컴파일 오류도 발생하지 않음).

  • 방문자 패턴 사용:

    public enum Country {
        CHINA {
            @Override
            public <T, J> T accept(CountryVisitor<T, J> visitor, J data) {
                return visitor.visitChina(data);
            }
        },
        INDIA {
            @Override
            public <T, J> T accept(CountryVisitor<T, J> visitor, J data) {
                return visitor.visitIndia(data);
            }
        },
        UNOTED_STATES {
            @Override
            public <T, J> T accept(CountryVisitor<T, J> visitor, J data) {
                return visitor.visitUnitedStates(data);
            }
        },
        BRAZIL {
            @Override
            public <T, J> T accept(CountryVisitor<T, J> visitor, J data) {
                return visitor.visitBrazil(data);
            }
        },
        MEXICO {
            @Override
            public <T, J> T accept(CountryVisitor<T, J> visitor, J data) {
                return visitor.visitMexico(data);
            }
        },
        GERMANY {
            @Override
            public <T, J> T accept(CountryVisitor<T, J> visitor, J data) {
                return visitor.visitGermany(data);
            }
        }
    };
    
    public abstract <T, J> T accept(CountryVisitor<T, J> visitor, J data);
    
    public interface CountryVisitor<T, J> {
            T visitChina(J data);
            T visitIndia(J data);
            T visitUnitedStates(J data);
            T visitBrazil(J data);
            T visitMexico(J data);
            T visitGermany(J data);
        }
    

    CountryVisitor의 사용법

    public class HappinessScoreCountryVisitor implements CountryVisitor<OutputDto, InputDto> {
    
       public OutputDto process(final Country country, final InputDto data) {
            country.accept(this, data);
        }
    
    // Implement all the methods and write the logic for each of the method
    
        @Override
        public OutputDto visitChina(InputDto data) {
           OutputDto output;
           // Logic here
           return output;
        }
    
        @Override
        public OutputDto visitIndia(InputDto data) {
           OutputDto output;
           // Logic here
           return output;
        }
    
        @Override
        public OutputDto visitUnitedStates(InputDto data) {
           OutputDto output;
           // Logic here
           return output;
        }
    
        @Override
        public OutputDto visitBrazil(InputDto data) {
           OutputDto output;
           // Logic here
           return output;
        }
    
        @Override
        public OutputDto visitMexico(InputDto data) {
           OutputDto output;
           // Logic here
           return output;
        }
    
        @Override
        public OutputDto visitGermany(InputDto data) {
           OutputDto output;
           // Logic here
           return output;
        }
    }
    


    이제 getHappinessScore 메서드는 다음과 같습니다.

    public float getHappinessScore(Country country) {
       InputDto input;
       /* Usually there would be an Input, incase Input is not require
       Write the visitor interface accordingly */
       return happinessScoreCountryVisitor.process(country, input);
    }
    


    스위치 케이스의 단점과 비교하여
  • 코드가 훨씬 깔끔해 보입니다.
  • 인적 오류 가능성은 거의 없습니다.
  • 새 국가를 추가하는 경우 컴파일 오류가 발생하므로 개발자는 모든 방문자 구현에서 구현해야 합니다.

  • 경고: 매우 간단한 사용 사례에 방문자 패턴을 오용하지 마십시오. 단순화하기보다는 복잡하게 만들 뿐입니다.
    전형적인 Visitor pattern example .

    그게 다야 🚀

    좋은 웹페이지 즐겨찾기