常用设计模式系列(十)—装饰者模式
第一节
前言
各位好,首先我要先恭喜下自己粉丝涨了几个,也谢谢各位的捧场,不过也跟我自己的努力密不可分,我也要继续加油,输出更好的文章来回报大家,也希望大家多提建议,有问题我也会及时改进。争取早日跟上各位大佬的步伐。
今天讲解的是创建型设计模式第三篇—装饰者模式(也叫修饰者模式),同样我们通过模式的名字去看实现过程,所谓装饰,就是在本体原有功能的基础上加上修饰,但不能更改原有本体的结构,使得原本的类在原有的结构不变动的基础上增加更多的功能,来拥有更多的功能,这个不修改本体去完成扩展的方式,就叫装饰者模式。
第二节
装饰者模式
装饰者(Decorator)模式的定义:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式。大多情况下,扩展一个类的功能许多人会选择继承的方式。但是继承的耦合度比较高,随着需要扩展功能的增加,子类会变得越来越复杂和臃肿,装饰者模式使用组合关系来创建一个包装对象来包含真实对象(原有对象),并且在原有对象的结构体不变的前提下,增加额外的功能,这个就是装饰者的实现过程。
我们小区楼下有一个卖鸡蛋灌饼的大妈,他们家每天的生意都很好,需要吃个灌饼都需要排队,一个基础版的灌饼就是灌饼+榨菜+生菜,在灌饼原有基础上老板也推出了套餐A和套餐B和豪华版套餐,A套餐可以加一种食物、B套餐可以加两种食物,豪华版就是三种食物,食物分别是辣条、煎蛋、烤肠,我和我的朋友对食物的喜欢程度不同,我喜欢加烤肠,我的朋友家底比较厚,他喜欢豪华版套餐,但是仔细想想,其实我们吃的都还是个灌饼,但是老板在原有灌饼的基础上进行修饰,抽象出了三个修饰的灌饼套餐版本,具体的套餐内容由每个顾客决定,这个不修改本体但又给本体扩展的过程,使用的就是修饰者模式。
第三节
代码实现
1.创建抽象构建“灌饼”类
package com.yang.decorator;
/**
* @ClassName AbstractComponent
* @Description 抽象构建角色灌饼
* @Author IT小白架构师之路
* @Date 2020/12/20 20:44
* @Version 1.0
**/
public interface AbstractPancake{
/**
* 灌饼可以吃
*/
public void eat();
}
2.创建具体构件角色“鸡蛋灌饼类”
package com.yang.decorator;
/**
* @ClassName EggPancake
* @Description 具体构件角色-鸡蛋灌饼
* @Author IT小白架构师之路
* @Date 2020/12/20 20:48
* @Version 1.0
**/
public class EggPancake implements AbstractPancake{
@Override
public void eat() {
System.out.println("鸡蛋灌饼本来有生菜、榨菜");
}
}
3.创建装饰抽象角色类
package com.yang.decorator;
/**
* @ClassName DecoratorPancake
* @Description 装饰抽象角色 装饰的鸡蛋灌饼的抽象
* @Author IT小白架构师之路
* @Date 2020/12/20 20:50
* @Version 1.0
**/
public class DecoratorPancake implements AbstractPancake{
//成员对象引入具体构件角色,就是要修饰的对象
private AbstractPancake abstractPancake;
//构造赋值具体构件
public DecoratorPancake(AbstractPancake abstractPancake){
this.abstractPancake = abstractPancake;
}
@Override
public void eat() {
abstractPancake.eat();
}
}
4.创建具体装饰角色A和B“灌饼套餐A和B”
package com.yang.decorator;
/**
* @ClassName ConcreteDecoratorPakageOne
* @Description 具体装饰者A套餐
* @Author IT小白架构师之路
* @Date 2020/12/20 20:53
* @Version 1.0
**/
public class ConcreteDecoratorA extends DecoratorPancake{
public ConcreteDecoratorA(AbstractPancake abstractPancake) {
super(abstractPancake);
}
@Override
public void eat() {
addOne();
super.eat();
}
/**
* 加一种吃的
*/
public void addOne(){
System.out.println("给鸡蛋灌饼增加了烤肠");
}
}
package com.yang.decorator;
/**
* @ClassName ConcreteDecoratorB
* @Description 具体装饰者B套餐
* @Author IT小白架构师之路
* @Date 2020/12/20 20:57
* @Version 1.0
**/
public class ConcreteDecoratorB extends DecoratorPancake{
public ConcreteDecoratorB(AbstractPancake abstractPancake) {
super(abstractPancake);
}
@Override
public void eat() {
addTwo();
super.eat();
}
public void addTwo(){
System.out.println("灌饼增加了烤肠、辣条");
}
}
5.创建客户端进行测试
package com.yang.decorator;
/**
* @ClassName Client
* @Description 客户端
* @Author IT小白架构师之路
* @Date 2020/12/20 20:59
* @Version 1.0
**/
public class Client {
public static void main(String[] args) {
//生成具体构件
AbstractPancake abstractPancake = new EggPancake();
//生成具体扩展构件A套餐
DecoratorPancake decoratorPancake = new ConcreteDecoratorA(abstractPancake);
//调用原有的基础方法
decoratorPancake.eat();
System.out.println("-------------我是分割线------------------");
//生成具体扩展构件B套餐
decoratorPancake = new ConcreteDecoratorB(abstractPancake);
decoratorPancake.eat();
}
}
6.程序运行结果如下,在原有的类结构保持不变的情况下完成装饰,增加更多的功能
给鸡蛋灌饼增加了烤肠
鸡蛋灌饼本来有生菜、榨菜
-------------我是分割线------------------
灌饼增加了烤肠、辣条
鸡蛋灌饼本来有生菜、榨菜
第四节
装饰者模式的优缺点及适用场景
优点:
1.在原有对象结构不变的情况下完成功能扩展,比较灵活。
2.装饰类可以增加多个,使用不同的装饰类可以完成不同的功能扩展。
3.具体构件类与具体装饰类可以独立变化,可以根据需要增加新的具体构件和具体装饰类,原类库不需要改变。
缺点:
1.使用装饰者模式,当需要的装饰场景较多时,会产生大量的具体装饰类,会增加系统资源占用,可能会影响程序性能。
2.使用装饰模式虽然比继承更灵活,但是当对象被多次修饰时,当程序运行过程中出现问题,排错过程会变得更加复杂。
适用场景:
1.需要在不影响原有对象的情况下,动态、透明的给原有对象扩展功能内容场景时。
2.不能采用继承的方式对原有对象进行扩展时,可以使用装饰模式。
扫描二维码
关注我吧
IT小白架构师之路