JavaRush /Java Blog /Random-KO /자바 데코레이터 패턴

자바 데코레이터 패턴

Random-KO 그룹에 게시되었습니다
책 '헤드 퍼스트. Eric Freeman과 Elizabeth Robson의 "디자인 패턴"은 이를 다음과 같이 정의합니다. 데코레이터 패턴은 객체에 새로운 기능을 동적으로 제공하며 기능 확장을 위한 하위 클래스화의 대안입니다. 예를 사용하여 이 정의를 더 자세히 살펴보겠습니다. 당신이 또 다른 현대 종교를 창설하고 사람들에게 그에 상응하는 서비스를 제공할 계획을 가지고 있다고 가정해 보십시오. 왜냐하면 현대의 경향은 채식주의, 생태학, 인간 발전을 추구하며 어떤 이유에서인지 사람들은 "전통적인" 종교(결국 무신론)에 만족하지 못합니다. 그렇다면 당신은 주류를 따라 또 다른 뉴에이지 종교(기존 종교로부터의 일종의 종합)를 창조합니다. 종교, 각각에서 좋아하는 것을 취함). 처음에는 다음과 같은 서비스를 제공합니다: 1. 운세 2. 운세 즉. 모든 것이 다음과 같습니다. 물론 가격과 설명이 포함된 서비스 인터페이스가 있습니다.
public interface Service {
    public double getPrice();
    public String getLabel();
}
및 서비스
public class Divination implements Service {
    private String label;
    private double price;

    public Divination(String label, double price) {
        this.label = label;
        this.price = price;
    }

    public double getPrice() {
        return this.price;
    }

    public String getLabel() {
        return this.label;
    }
}
public class Horoscope implements Service {
    private String label;
    private double price;

    public Horoscope(String label, double price) {
        this.label = label;
        this.price = price;
    }

    public double getPrice() {
        return this.price;
    }

    public String getLabel() {
        return this.label;
    }
}
따라서 2가지 주문이 나타났습니다(타로 카드를 사용한 운세 및 고객의 개인 별자리 운세).
public static void main(String[] args) {
    double cost;
    // Гадание на Таро
    Service taro = new Divination("Таро", 1000);
    // И персональный гороскоп
    Service personalHoroscope = new Horoscope("Персональный гороскоп", 9000);
    cost = taro.getPrice() + personalHoroscope.getPrice();

    System.out.println(cost);
}
그리고 프로그램의 결과는 다음과 같습니다.
10000.0
모든 것이 괜찮을 것입니다. 그러나 이미 수천 명은 아니더라도 수백 명이 여러분과 같은 사람들이 있으며 우리는 사람들의 영성을 계속 발전시켜야 합니다. 그렇지 않으면 그들은 더 이상 관심을 갖지 않습니다. 따라서 기존 서비스에 추가 옵션을 옵션으로 제공하게 되었습니다. 예를 들어, 운세 서비스(타로 또는 커피 찌꺼기)를 선택할 때 추가 옵션으로 차크라 또는 오라의 특성을 주문할 수 있습니다(각각 비용은 자체적임). 모든 것이 이미 올바르게 구성되고 계산된 기존 서비스 클래스를 변경하지 않도록 이를 어떻게 구현할 수 있습니까? 현재 Divination에 Divination + Chakras 또는 Divination + Aura 클래스를 추가로 만들 수 있습니다.
public class Divination implements Service {
    // Здесь своя стоимость и другие методы
}
public class DivinationWithChakras implements Service {
    // Здесь своя стоимость и другие методы
}
public class DivinationWithAura implements Service {
    // Здесь своя стоимость и другие методы
}
아니면 그냥 서브클래싱을 사용하세요. 부모 클래스를 자식 클래스로 확장
public class DivinationWithAura extends Divination {
    public DivinationWithAura(String label, double price) {
        super(label, price);
    }
    // Здесь своя стоимость и другие методы
}
public class DivinationWithChakras extends Divination {
    public DivinationWithChakras(String label, double price) {
        super(label, price);
    }
    // Здесь своя стоимость и другие методы
}
그러나 단점은 즉시 눈에 띄고 전 세계의 영성을 발전시키고 새로운 추가 옵션을 갖게 될 수 있으며 이는 새로운 클래스를 의미하며 여전히 현재 클래스를 결합해야한다면 클래스는 빠르게 성장할 것입니다. 두 가지 옵션을 함께 사용하고 별도로 별도로 사용하지 않는 운세 수업으로 충분합니다.
public class DivinationWithChakrasAndAura implements Service {
    // Здесь своя стоимость и другие методы
}
여기가 Java에서 매우 "절약적인" 데코레이터 패턴을 사용할 수 있는 곳입니다. 이를 위해 서비스를 구현하고 서비스도 포함하는 추가 옵션에 대한 클래스를 생성합니다. 따라서 운세를 주문해야하고 두 가지 옵션을 함께 사용해도 다음과 같이 보일 것입니다. 인터페이스는 처음부터 그랬습니다.
public interface Service {
    public double getPrice();
    public String getLabel();
}
2가지 서비스 등급, 이전과 동일:
public class Divination implements Service {
    private String label;
    private double price;

    public Divination(String label, double price) {
        this.label = label;
        this.price = price;
    }

    public double getPrice() {
        return this.price;
    }

    public String getLabel() {
        return this.label;
    }
}
public class Horoscope implements Service {
    private String label;
    private double price;

    public Horoscope(String label, double price) {
        this.label = label;
        this.price = price;
    }

    public double getPrice() {
        return this.price;
    }

    public String getLabel() {
        return this.label;
    }
}
추가 옵션을 위한 데코레이터
public class OptionDecorator implements Service {
    private Service service;
    private String label;
    private double price;

    public OptionDecorator(Service service, String label, double price) {
        this.service = service;
        this.label = label;
        this.price = price;
    }

    public double getPrice() {
        return this.price + service.getPrice();
    }

    public String getLabel() {
        return this.label + service.getLabel();
    }
}
그리고 옵션 자체(지금까지 2개):
public class Aura extends OptionDecorator {
    public Aura(Service service) {
        super(service, "Характеристика ауры", 1500);
    }
}
public class Chakra extends OptionDecorator {
    public Chakra(Service service) {
        super(service, "Характеристика чакр", 500);
    }
}
글쎄요, 주문 자체는
public static void main(String[] args) {
    // Гадание на Таро
    Service taro = new Divination("Таро", 1000);
    Service chakra = new Chakra(taro);
    Service aura = new Aura(chakra);

    // И общая стоимость
    System.out.println(aura.getPrice());
}
3000.0
이는 기본 서비스와 2개의 추가 옵션을 합한 결과를 제공합니다. 즉, 모든 추가 작업이 필요하지 않습니다. 옵션(또는 둘 다의 조합)을 사용하여 새 클래스를 생성합니다. 또한, 이러한 옵션은 운세 서비스뿐만 아니라 운세 서비스에도 적용 가능합니다. 따라서 가까운 시일 내에 다음과 같은 추가 옵션을 구현해야 할 경우: - 소셜 네트워크에서 아바타 파트너의 호환성 - 원격 채널링을 통한 현금 흐름 개선, 2개의 추가 클래스만 작성하면 됩니다.
public class Channeling extends OptionDecorator {
    public Channeling(Service service) {
        super(service, "Полет в Поле Чудес", 99999);
    }
}
public class Avatar extends OptionDecorator {
    public Avatar(Service service) {
        super(service, "Ваша любовь в соц сетях", 5555);
    }
}
모든 서비스에 추가할 수 있습니다.
public static void main(String[] args) {
    // Гадание на Таро
    Service taro = new Divination("Таро", 1000);
    Service chakra = new Chakra(taro);
    Service aura = new Aura(chakra);

    // И общая стоимость
    System.out.println(aura.getPrice());

    // Гороскоп
    Service horoscope = new Horoscope("Персональный гороскоп", 1000);
    Service channenling = new Channeling(horoscope);
    Service avatar = new Avatar(channenling);

    // И общая стоимость
    System.out.println(avatar.getPrice());
}
그리고 (우리에게 필요한) 프로그램의 결과:
3000.0
106554.0
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION