设计模式—结构型—装饰者模式

前言

这个模式写起来很简单(但是融会贯通并不简单),核心的类就3个。所谓装饰者模式就是基于如下三个类来展开的。

概念

  • 基础抽象类(Coffee)
    这个类定义了被装饰的对象具备哪些属性,在本文案例中即:价格price,名称name。

  • 标准模板类(SimpleCoffe)
    这是装饰者模式的一个体现,它是基础抽象类的一个实现,因为基础抽象类是抽象的,我们无法具体的去设置它的属性,所以我们需要定义这么一个模板产品来让我们接下来需要扩展创建的子类使用。那么它存在的意义是啥?它存在的意义就是作为一个参数装饰者接收。

  • 装饰者类(CoffeeDecorator)
    这是装饰者模式的核心体现,它接收一个模板产品,并再其基础之上进行“装饰(或者说是修改)”

代码结构如下:

类图

摘自:https://blog.csdn.net/gdutxiaoxu/article/details/51885105

理解

我个人觉得这个装饰者比较别扭的地方就在于,它里边的这个装饰者Decorator稍微有点点绕,因为,我们创建一个具体的装饰产品,比如牛奶咖啡,我们并不是直接去继承咖啡的基类,而是去继承的CoffeeDecorator这个类,这样在逻辑上就会产生一种分离感,而实际上并不是完全分离的,因为我们的CoffeeDecorator也是Coffee抽象类的一个子类(另一个是模板咖啡类,用来当做参数),也就是说,光是Coffee这个基类就产生出了俩个不同作用的子类,他们一个用来作为参数(或者说是装饰的原材料),一个用来作为装饰器(接收模板咖啡,专门用来做装饰,这里也体现了组合的思想)。我想,这也是”装饰设计模式”的体现之处,即:在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。

代码

本文代码按照如下流程来写:

  • 创建咖啡抽象类
  • 创建咖啡模板类(非抽象)
  • 创建装饰者(组合思想,接收咖啡模板类,在原有基础上进行修改)
  • 创建业务类,牛奶咖啡(继承自装饰者)
  • 创建业务类,焦糖咖啡(继承自装饰者)
  • 创建测试类,并观察输出结果。

ok,let’s go。

创建咖啡抽象类


package com.zj.dp.装饰者模式.base;

public abstract class Coffee {

    abstract int getPrice();

    abstract String getName();

    @Override
    public String toString() {
        return getName() + " ___ price :" + getPrice();
    }
}

创建咖啡模板类(非抽象)


package com.zj.dp.装饰者模式.base;

public class SimpleCoffe extends Coffee {

    @Override
    int getPrice() {
        return 0;
    }

    @Override
    String getName() {
        return null;
    }
}

创建装饰者(组合思想,接收咖啡模板类,在原有基础上进行修改)


package com.zj.dp.装饰者模式.base;

public class CoffeeDecorator extends Coffee {

    protected Coffee mCoffee;

    public CoffeeDecorator(Coffee mCoffee) {
        this.mCoffee = mCoffee;
    }

    @Override
    protected int getPrice() {
        return 0;
    }

    @Override
    protected String getName() {
        return "Coffee";
    }
}

创建业务类,牛奶咖啡(继承自装饰者)


package com.zj.dp.装饰者模式;

import com.zj.dp.装饰者模式.base.Coffee;
import com.zj.dp.装饰者模式.base.CoffeeDecorator;

public class MilkCoffe extends CoffeeDecorator {


    public MilkCoffe(Coffee mCoffee) {
        super(mCoffee);
    }

    @Override
    protected int getPrice() {
        return super.getPrice() + 20;
    }

    /**
     * @return
     */
    @Override
    protected String getName() {
        return "Milk " + super.getName();
    }
}

创建业务类,焦糖咖啡(继承自装饰者)


package com.zj.dp.装饰者模式;

import com.zj.dp.装饰者模式.base.Coffee;
import com.zj.dp.装饰者模式.base.CoffeeDecorator;

public class SugarCoffe extends CoffeeDecorator {

    public SugarCoffe(Coffee mCoffee) {
        super(mCoffee);
    }


    @Override
    protected String getName() {
        return "Sugar "+super.getName();
    }

    @Override
    protected int getPrice() {
        return super.getPrice() + 10;
    }
}

创建测试类,并观察输出结果。

java代码:


    package com.zj.dp.装饰者模式;

    import com.zj.dp.装饰者模式.base.SimpleCoffe;

    public class Test {

        public static void main(String[] args) {
            MilkCoffe milkCoffe = new MilkCoffe(new SimpleCoffe());
            SugarCoffe sugarCoffe = new SugarCoffe(new SimpleCoffe());
            System.out.println(milkCoffe);
            System.out.println(sugarCoffe);
        }
    }

输出结果:


    Milk Coffee ___ price :20
    Sugar Coffee ___ price :10

    Process finished with exit code 0

挖个巨坑

装饰者,适配器,静态代理,等模式的异同:
https://blog.csdn.net/albertfly/article/details/52276708

Demo

https://github.com/zj614android/designPattern/tree/master/app/src/main/java/com/zj/dp/%E8%A3%85%E9%A5%B0%E8%80%85%E6%A8%A1%E5%BC%8F

Thanks

https://blog.csdn.net/gdutxiaoxu/article/details/51885105

猜你喜欢

转载自blog.csdn.net/user11223344abc/article/details/81384637
今日推荐