[design-patterns] 코드에서 스위치를 제거하는 방법 [닫기]

코드에서 스위치를 사용하지 않는 방법은 무엇입니까?



답변

스위치 문은 그 자체로 반 패턴이 아니지만 객체 지향을 코딩 하는 경우 스위치 문을 사용하는 대신 다형성 으로 스위치 사용을 더 잘 해결할 수 있는지 고려해야합니다 .

다형성을 사용하면 다음과 같습니다.

foreach (var animal in zoo) {
    switch (typeof(animal)) {
        case "dog":
            echo animal.bark();
            break;

        case "cat":
            echo animal.meow();
            break;
    }
}

이된다 :

foreach (var animal in zoo) {
    echo animal.speak();
}


답변

스위치 선언문 냄새 참조 :

일반적으로 유사한 스위치 문이 프로그램 전체에 흩어져 있습니다. 하나의 스위치에서 절을 추가하거나 제거하면 다른 스위치도 찾아서 복구해야합니다.

리팩토링패턴 리팩토링 모두이 문제를 해결하는 방법이 있습니다.

(의사) 코드가 다음과 같은 경우

class RequestHandler {

    public void handleRequest(int action) {
        switch(action) {
            case LOGIN:
                doLogin();
                break;
            case LOGOUT:
                doLogout();
                break;
            case QUERY:
               doQuery();
               break;
        }
    }
}

이 코드는 공개 폐쇄 원칙을 위반하며 발생 하는 모든 새로운 유형의 조치 코드에 취약합니다. 이를 해결하기 위해 ‘Command’객체를 도입 할 수 있습니다.

interface Command {
    public void execute();
}

class LoginCommand implements Command {
    public void execute() {
        // do what doLogin() used to do
    }
}

class RequestHandler {
    private Map<Integer, Command> commandMap; // injected in, or obtained from a factory
    public void handleRequest(int action) {
        Command command = commandMap.get(action);
        command.execute();
    }
}

(의사) 코드가 다음과 같은 경우

class House {
    private int state;

    public void enter() {
        switch (state) {
            case INSIDE:
                throw new Exception("Cannot enter. Already inside");
            case OUTSIDE:
                 state = INSIDE;
                 ...
                 break;
         }
    }
    public void exit() {
        switch (state) {
            case INSIDE:
                state = OUTSIDE;
                ...
                break;
            case OUTSIDE:
                throw new Exception("Cannot leave. Already outside");
        }
    }

그런 다음 ‘State’객체를 소개 할 수 있습니다.

// Throw exceptions unless the behavior is overriden by subclasses
abstract class HouseState {
    public HouseState enter() {
        throw new Exception("Cannot enter");
    }
    public HouseState leave() {
        throw new Exception("Cannot leave");
    }
}

class Inside extends HouseState {
    public HouseState leave() {
        return new Outside();
    }
}

class Outside extends HouseState {
    public HouseState enter() {
        return new Inside();
    }
}

class House {
    private HouseState state;
    public void enter() {
        this.state = this.state.enter();
    }
    public void leave() {
        this.state = this.state.leave();
    }
}

도움이 되었기를 바랍니다.


답변

스위치는 스위치 문으로 구현되는지 여부에 관계없이 체인, 룩업 테이블, oop 다형성, 패턴 일치 또는 다른 것입니다.

switch statement “또는 ” switch pattern “을 사용하지 않겠습니까? 첫 번째 것은 다른 패턴 / 알고리즘을 사용할 수있는 경우에만 제거 할 수 있으며, 대부분 불가능하거나 더 나은 방법은 아닙니다.

코드 에서 switch 문 을 제거하려면 첫 번째 질문 은 switch 문을 제거하고 다른 기술을 사용 하는 것이 합리적 입니다. 불행히도이 질문에 대한 답변은 도메인마다 다릅니다.

컴파일러는 명령문을 전환하기 위해 다양한 최적화를 수행 할 수 있습니다. 예를 들어, 메시지 처리를 효율적으로 수행하려면 switch 문을 사용하는 것이 좋습니다. 그러나 다른 한편으로는 switch 문을 기반으로 비즈니스 규칙을 실행하는 것이 가장 좋은 방법은 아니며 응용 프로그램을 재구성해야합니다.

switch 문에 대한 대안은 다음과 같습니다.


답변

스위치 자체는 그렇게 나쁘지는 않지만 메서드의 객체에 “스위치”또는 “if / else”가 많은 경우 디자인이 약간 “절차 적”이고 객체가 가치가 있다는 신호일 수 있습니다 양동이. 논리를 객체로 옮기고 객체에서 메소드를 호출 한 다음 대신 응답 방법을 결정하도록합니다.


답변

가장 좋은 방법은 좋은지도를 사용하는 것입니다. 사전을 사용하면 거의 모든 입력을 다른 값 / 객체 / 함수에 매핑 할 수 있습니다.

코드는 다음과 같이 보일 것입니다.

void InitMap(){
    Map[key1] = Object/Action;
    Map[key2] = Object/Action;
}

Object/Action DoStuff(Object key){
    return Map[key];
}


답변

모두가 거대한 if else블록을 좋아 합니다. 너무 쉽게 읽을 수 있습니다! 그래도 스위치 문을 제거하려는 이유가 궁금합니다. switch 문이 필요한 경우 switch 문이 필요할 수 있습니다. 진지하게, 나는 그것이 코드가하는 일에 달려 있다고 말합니다. 모든 스위치가 함수를 호출하는 중이라면 함수 포인터를 전달할 수 있습니다. 더 나은 솔루션 인지 여부 는 논쟁의 여지가 있습니다.

언어도 여기서 중요한 요소라고 생각합니다.


답변

나는 당신이 찾고있는 것이 전략 패턴이라고 생각합니다.

이것은 여러 가지 방법으로 구현 될 수 있으며, 다음과 같이이 질문에 대한 다른 답변에서 언급되었습니다.

  • 값의 맵-> 함수
  • 다형성. (객체의 하위 유형은 특정 프로세스를 처리하는 방법을 결정합니다).
  • 일급 기능.