JavaRush /Java 博客 /Random-ZH /Java 装饰器模式

Java 装饰器模式

已在 Random-ZH 群组中发布
在《头第一。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
一切都会好起来的,但已经有数百人,甚至数千人像你一样,我们需要继续发展人们的灵性,否则他们不再感兴趣。因此,提供了当前服务的附加选项作为选项。例如,当选择算命服务(塔罗牌或咖啡渣)时,作为附加选项,您可以订购脉轮或光环的特征(每个都有自己的成本)。如何实现这一点,以免对现有服务类进行更改,其中所有内容都已正确配置和计算。您可以为当前占卜创建额外的类别占卜+脉轮或占卜+光环:
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 中非常“节省”的装饰器模式。为此,我们将为附加选项创建一个类,该类也将实现 Service,但也包含 Service。相应地,当我们需要下单算命的时候,即使有2个选项在一起,也会是这样的: 界面一开始就是这样的
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