设计模式:装饰者模式

 

前言

装饰者(Decorator)模式动态地将责任附加到对象上,若要扩展功能,装饰者模式提供了比继承更加有弹性的替代方案(来自 Head First 设计模式)

 UML图

Component:组件接口,每个组件都可以单独使用。也可以被装饰者包装起来使用。

Concrete:具体的组件。扩展自组件接口

Decorator:装饰者接口。

ConcreteDecorator:具体的装饰者。

例子:

需求是旅游的景区需要买门票,但是门票价格不只是原始的价格。针对不同的情况会有不同的价格变化。可能有国庆时候的折扣,也可以有许多类型的优惠券折扣,也可能在基本门票上进行更全面的服务,比如VIP全天包游服务。。。

门票主体

/**
 * 组件接口
 * @author lzp
 *
 */
public abstract class Ticket {
    public String description = "未知门票种类";
    public String getDescription() {
        return description;
    }
    //价格计算
    public abstract double price();
}

具体的门票(具体的景区门票的种类和基本价格可以从数据库中取,这里仅是演示一下装饰者模式)

public class ScenicTicket extends Ticket{
    public ScenicTicket() {
        description = "景区门票";
    }
    @Override
    public double price() {
        return 100;
    }
    
}

装饰者抽象类

/**
 * 门票装饰者抽象类
 * @author lzp
 *
 */
public abstract class TicketDecorator extends Ticket{
    
    public abstract String getDescription();
}

装饰者具体类

国庆优惠价

//国庆优惠
public class NationalDay extends TicketDecorator{
    Ticket ticket;
    public NationalDay(Ticket ticket) {
        this.ticket = ticket;
    }
    @Override
    public String getDescription() {
        return ticket.getDescription()+","+"国庆优惠";
    }
    @Override
    public double price() {
        return ticket.price()-20;
    }
}

优惠券

//优惠券
public class Coupon extends TicketDecorator{
    Ticket ticket;
    public Coupon(Ticket ticket) {
        this.ticket = ticket;
    }
    @Override
    public String getDescription() {
        return ticket.getDescription()+","+"1号优惠劵";
    }
    @Override
    public double price() {
        return ticket.price()-10;
    }
}

VIP服务

public class VIPService extends TicketDecorator{
    Ticket ticket;
    public VIPService(Ticket ticket) {
        this.ticket = ticket;
    }
    @Override
    public String getDescription() {
        return ticket.getDescription()+","+"VIP全天包邮服务";
    }
    @Override
    public double price() {
        return ticket.price()+688;
    }
}

测试代码

public class Main {

    public static void main(String[] args) {
        //买一张普通门票
        Ticket ticket = new ScenicTicket();
        System.out.println(ticket.getDescription()+ticket.price());
        //想要VIP服务的门票
        Ticket ticket2 = new ScenicTicket();
        ticket2 = new VIPService(ticket2);
        System.out.println(ticket2.getDescription()+ticket2.price());
        //买一张VIP服务门票,有国庆优惠和优惠券
        Ticket ticket3 = new ScenicTicket();
        ticket3 = new VIPService(ticket3);
        ticket3 = new NationalDay(ticket3);
        ticket3 = new Coupon(ticket3);
        System.out.println(ticket3.getDescription()+ticket3.price());
    }

}

 

 总结:

实际的代码中对于相似的代码,比如各种优惠券之类的,也可以再次进行封装接口。便于调用。

装饰者模式是在不改变原有接口的前提下增强对象的性能。

但是会产生比较多的装饰者类。

posted @ 2019-03-02 15:20  发包哥哥  阅读(147)  评论(0编辑  收藏  举报