博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
23种设计模式之装饰者模式
阅读量:5859 次
发布时间:2019-06-19

本文共 3787 字,大约阅读时间需要 12 分钟。

装饰者模式:动态的将新功能(装饰者,如调料)附加到对象(主体,如单品咖啡)上。在对象功能扩展方面,它比继承更有弹性。

1、以咖啡馆订单系统项目为例

咖啡种类:Espresso、ShortBlack、LongBlack、Decaf

调料:Milk、Soy、Chocolate

咖啡可以点单品,也可以和任意调料混合,最后返回咖啡价格

一个差的方案,为每一个单品和单品与调料组合,创建类,如Espresso类、ShortBlack类、Espresso&Milk类、Espresso&Milk&Soy类等,每个类里返回咖啡价格,这种方案导致类爆炸

稍微好点但是也不好的方案是,设计一个抽象超类,把调料内置到超类中,可设置添加调料方法,在单品继承自超类的实现类里,通过判断是否设置有某种调料,再计算价钱,这种设计太繁琐,而且不易扩展,如要新增一种调料,那就要改动代码,容易出错

2、装饰者模式设计:

装饰者设计模式是通过递归方式调用对象方法的,装饰者要继承自抽象主体,并且会调用抽象主体的方法,装饰者是依附于主体的

形如new Chocolate(new Chocolate(new Milk(new LongBlack))),如果返回价格调用cost方法,由于装饰者(调料)也继承自主体(Drink),而且调料.cost方法中会调用drink中的cost,一直递归调用到单品的cost方法

3、装饰者模式代码示例

//主体类public abstract class Drink {    private String description = "";    private float price = 0f;    public String getDescription() {        return description + "-" + this.price;    }    public void setDescription(String description) {        this.description = description;    }    public float getPrice() {        return price;    }    public void setPrice(float price) {        this.price = price;    }    //单品中返回价格,调料中要加上单品价格    public abstract float cost();}
抽象主体Drink 有description和price属性来定义继承自主体的单品描述和价格,抽象方法cost用来计算单品或混合咖啡总消费
//主体中间层public class Coffee extends Drink {    public float cost() {        return super.getPrice();    }}
设置中间层Coffee extends Drink,所有单品都继承自Coffee,单品的消费就是单品的价格
public class Decaf extends Coffee {    public Decaf() {        super.setDescription("Decaf");        super.setPrice(3.0f);    }}
Decaf extends Coffee单品构造中初始化描述及价格
public class Espresso extends Coffee {    public Espresso() {        super.setDescription("Espresso");        super.setPrice(4.0f);    }}
Espresso extends Coffee单品构造中初始化描述及价格
public class LongBlack extends Coffee {    public LongBlack() {        super.setDescription("LongBlack");        super.setPrice(5.0f);    }}
LongBlack extends Coffee单品构造中初始化描述及价格
public class ShortBlack extends Coffee {    public ShortBlack() {        super.setDescription("ShortBlack");        super.setPrice(6.0f);    }}
ShortBlack extends Coffee单品构造中初始化描述及价格
//装饰者中间层public class Decorator extends Drink {    //可以是单品也可以是被包装过的单品    private Drink drink;    public Decorator(Drink drink) {        this.drink = drink;    }    public float cost() {        //返回装饰者(调料)的价格+单品或者被包装过的单品的价格(被包装过的单品就是继承自装饰者的调料)        return super.getPrice() + drink.cost();    }    @Override    public String getDescription() {        return super.getDescription() + "&&" + drink.getDescription();    }}
装饰者中间层Decorator extends Drink,装饰者依附于主体或混合主体,所以要有主体或混合主体对象,其cost总消费为装饰者价格加上主体或混合主体消费,描述为装饰者描述和主体描述
public class Chocolate extends Decorator {    public Chocolate(Drink drink) {        super(drink);        super.setDescription("Chocolate");        super.setPrice(3.0f);    }}
Chocolate extends Decorator装饰者依附于主体或混合主体,所以构造中传入主体,设置装饰者描述及价格
public class Milk extends Decorator {    public Milk(Drink drink) {        super(drink);        super.setDescription("Milk");        super.setPrice(2.0f);    }}
Milk extends Decorator装饰者依附于主体或混合主体,所以构造中传入主体,设置装饰者描述及价格
public class Soy extends Decorator {    public Soy(Drink drink) {        super(drink);        super.setDescription("Soy");        super.setPrice(1.0f);    }}
Soy extends Decorator装饰者依附于主体或混合主体,所以构造中传入主体,设置装饰者描述及价格

测试代码:

public class CoffeeBar {    public static void main(String[] args) {        Drink order;        order = new Decaf();        System.out.println("order price:" + order.cost());        System.out.println("order desc:" + order.getDescription());        System.out.println("***********************************");        order = new LongBlack();        order = new Milk(order);        order = new Chocolate(order);        order = new Chocolate(order);        System.out.println("order2 price:" + order.cost());        System.out.println("order2 desc:" + order.getDescription());    }}
应用测试代码CoffeeBar

 

转载地址:http://sxrjx.baihongyu.com/

你可能感兴趣的文章
【深入浅出express】- express入门01
查看>>
Vue核心部分实现,总共分三步,第一步.....
查看>>
http调用docker API创建容器
查看>>
Safari无痕模式下,storage被禁用问题
查看>>
Sentinel 原理-实体类
查看>>
服务端性能优化方案
查看>>
Android Animation 概述
查看>>
记一道控制并行数的前端面试题
查看>>
关于写作那些事之利用 js 统计各大博客阅读量
查看>>
macrotasks&microtasks引发的思考
查看>>
实现Vue-MVVM-step1
查看>>
Android Studio集成讯飞语音导出可供Unity使用的jar/aar
查看>>
Android 四大组件生命周期
查看>>
Java Activiti 工作流引擎 springmvc SSM 流程审批 后台框架源码
查看>>
一入前端深似海
查看>>
谈谈流计算中的『Exactly Once』特性
查看>>
短视频APP开发,抖音源码,行业差异化详解
查看>>
水果电商小程序云开发,从零到上线投入使用
查看>>
mybatis-plus生成xml中文乱码
查看>>
消息队列之 RabbitMQ
查看>>