装饰者模式介绍

前言:好像挺久没写过博客了,大概是变懒了没有开始那会儿的动力了,但是,学习以及记录的习惯还是不能丢的。OK,本文主要介绍java装饰者模式

一 什么是装饰者模式

就定义而言:装饰者模式指的是 -> 在不改变源代码的情况下,动态地给一个对象添加一些额外的职责。通过创建一个包装对象,也就是装饰者来包裹被装饰的对象。就增加功能来说,装饰者模式比生成子类(继承)更加灵活。

装饰者模式的作用,简单的说就是,扩展原来有类的功能。怎么样,是不是马上就想到了代理模式?
其实两者还是有区别的,装饰者模式重点在于灵活的扩展原有类的功能,而代理模式重点在于控制对对象的访问。具体就不多说了,有兴趣的朋友可以自行了解。

二 装饰者模式的组成

  1. 抽象组件Component

    其实就是被装饰者的基类,一个接口,主要用来规范被装饰对象。

  2. 具体组件ConcreteComponent

    其实就是具体的被装饰者,实现被装饰者的基类,也就是抽象组件。

  3. 装饰者抽象类Decorator

    其实就是装饰者的基类,一个抽象类。用于规范以及组合具体的装饰者,进而实现灵活的对被装饰者进行装饰。Decorator必须持有抽象组件的对象实例引用

  4. 具体装饰者ConcreteDecorator

    具体的装饰者,继承抽象的装饰者,具体为被装饰者增加什么功能就在这里得到体现。

三 装饰者模式具体实现

由于本人比较喜欢锻炼,没事的时候经常会去健身房活动活动筋骨(哈哈,预防猝死,从我做起)。所以,这里我就以健身房办卡为例,有的健身房单纯办一张年卡的话,就只能享受器械以及跑步机的使用权。对于其他的舞蹈,瑜伽,游泳等等之类的,则需要重新办理相应的业务。

所以,健身卡就会有很多种组合了。例如:1.年卡 2.年卡+游泳 3.年卡+舞蹈 4.年卡+瑜伽+舞蹈…
如果采用继承的方式实现健身卡,那么会有很多个类,很容易造成类爆炸,相比继承,装饰者模式在一定程度上可以大大减少类爆炸的问题。

OK,说了这么多是为了帮助大家更好的理解。接下来,直接上代码:

1.抽象组件(抽象的被装饰者)

/**
 * 抽象的组件(抽象的被装饰者)
 * <p>
 * 这里以健身卡为例 健身卡有价格以及描述
 */
public interface GymCard {

    //价格
    public BigDecimal price();

    //描述
    public String desc();

}

2.具体组件(具体的被装饰者)

/**
 * 具体组件(具体的被装饰者)
 * 这是一张最原始的健身卡,只能使用跑步机以及器械
 * 需要实现抽象组件,并实现规定的相应方法
 */
public class BasicGymCard implements GymCard {

    @Override
    public BigDecimal price() {
        return BigDecimal.valueOf(1500L);
    }

    @Override
    public String desc() {
        return "健身年卡";
    }

}

3.装饰者抽象类Decorator

/**
 * 装饰者组件(装饰者抽象类)
 * 1:需要实现抽象组件 
 * 2:需要持有抽象组件的对象实例引用
 */
public abstract class Decorator implements GymCard {

    //持有抽象组件的对象实例引用 通过构造函数传入
    private GymCard gymCard;

    public Decorator(GymCard gymCard) {
        this.gymCard  = gymCard;
    }

    @Override
    public BigDecimal price() {
        return gymCard.price();
    }

    @Override
    public String desc() {
        return gymCard.desc();
    }

}

4.具体装饰者ConcreteDecorator

/**
 * 具体的装饰者之游泳业务
 * 需要继承抽象的装饰者,并重写其方法,完成相应的功能增强
 */
public class Swim extends Decorator {

    public Swim(GymCard gymCard) {
        super(gymCard);
    }

    @Override
    public BigDecimal price() {
        return super.price().add(BigDecimal.valueOf(400L));
    }

    @Override
    public String desc() {
        return super.desc() + "+游泳";
    }

}

此外,瑜伽以及舞蹈和游泳是一样的,都是健身卡具体的装饰者,代码是一样的,我就不重复贴出来了。

OK,接下来看测试类:

public class Test {

    public static void main(String[] args) {
        //基本的健身卡
        GymCard gymCard = new BasicGymCard();
        System.out.println(gymCard.desc());
        System.out.println(gymCard.price());

        //加瑜伽
        GymCard yoGa = new Yoga(gymCard);
        System.out.println(yoGa.desc());
        System.out.println(yoGa.price());

        //再加舞蹈
        GymCard dance = new Dance(yoGa);
        System.out.println(dance.desc());
        System.out.println(dance.price());

        //加游泳
        GymCard swim = new Swim(gymCard);
        System.out.println(swim.desc());
        System.out.println(swim.price());
    }

}

运行结果如下:
在这里插入图片描述
可以看到,我们可以随意组合装饰者,从而将健身卡的功能得到扩展。

最后,我们可以看看装饰者模式的UML类图
在这里插入图片描述
好了,关于装饰者模式的介绍就到这里了。
在JDK里面,IO流就是典型的装饰者模式的应用,感兴趣的朋友可以去看看IO流的源代码或者UML类图~

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值