设计模式(4):装饰者模式

一、概念

1、定义:在不改变原有对象的基础上,动态地将“责任”附加到对象上。装饰者提供了比继承更有弹性的替代方案(扩展原有对象功能)

2、类型:结构型

3、适用场景

  • 扩展一个类的功能,或给一个类添加职责
  • 动态的给一个对象添加功能。并且这些功能可以动态的撤销

4、优缺点

优点

  • 比继承更加灵活,在不改变原有对象的基础之上给一个对象扩展功能(原来是用继承来扩展功能,如果功能繁多,必然要用到很多子类,增加系统复杂性,并且使用继承实现功能扩展是静态的,我们必须可预见这些扩展功能,装饰者模式是动态的添加职责!)
  • 通过使用不同的装饰类,以及这些装饰类的组合,可以达到不同的效果。
  • 符合OCP,可以扩展行为,装饰者和被装饰者都能独立变化,原有代码不用改变。

缺点

  • 增加更多的类,增加程序复杂性
  • 动态装饰和多层装饰会更加复杂

5、相关设计模式

  • 装饰者模式和代理模式

    职责不同,装饰者模式是在一个对象上动态的添加方法,代理模式是控制对对象的访问,代理也能做功能的增强,装饰者更多考虑的是功能扩展。代理模式可以为它的客户隐藏对象的具体信息,此外,使用装饰者模式是把原始对象传进构造器,而代理模式是创建一个对象的实例。

  • 装饰者模式和适配器模式

装饰者和适配器模式都是包装模式(Wrapper Pattern),装饰者也是一种特殊的代理模式。

装饰者模式适配器模式
形式是一种非常特别的适配器模式没有层级关系,装饰器模式有层级关系
定义装饰者和被装饰者都实现同一个接口,主要目的是为了扩展之后依旧保留 OOP 关系适配器和被适配者没有必然的联系,通常是采用继承或代理的形式进行包装
关系满足 is-a 的关系满足 has-a 的关系
功能注重覆盖、扩展注重兼容、转换
设计前置考虑后置考虑

5、UML
在这里插入图片描述
装饰者和被装饰者必须是一样的类型,它们继承了共同的超类,这是关键,利用继承获得了类型匹配,而不是继承它的行为,行为是来自装饰者自身以及其他的基础组件,或者是装饰者-装饰者之间的组合关系。
PS:图中最顶部component类型是抽象类,当然java中也可以使用接口

二、Coding

背景,买鸡蛋饼,加鸡蛋,加香肠。。。

我们要有抽象的实体类、确定的实体类,以及抽象的装饰者,确定的装饰者

被装饰得实体是煎饼,装饰者是鸡蛋和香肠

// 抽象实体类
public abstract class ABattercake {
    protected abstract String getDesc();
    protected abstract int cost();
}
// 确定实体类
public class Battercake extends ABattercake {
    @Override
    protected String getDesc() {
        return "煎饼";
    }
    @Override
    protected int cost() {
        return 8;
    }
}
// 抽象装饰者  继承 抽象实体类,此时抽象装着者与确定的实体类都是抽象实体类的字类
// 集体装饰者继承这个抽象装饰者达到增强类的功能的目的
public abstract class AbstractDecorator extends ABattercake {
    private ABattercake aBattercake;
    public AbstractDecorator(ABattercake aBattercake) {
        this.aBattercake = aBattercake;
    }

    protected abstract void doSomething();

    @Override
    protected String getDesc() {
        return this.aBattercake.getDesc();
    }

    @Override
    protected int cost() {
        return this.aBattercake.cost();
    }
}
// 具体装饰者1
public class EggDecorator extends AbstractDecorator {
    public EggDecorator(ABattercake aBattercake) {
        super(aBattercake);
    }
    @Override
    protected void doSomething() {
    }
    @Override
    protected String getDesc() {
        return super.getDesc()+" 加一个鸡蛋";
    }
    @Override
    protected int cost() {
        return super.cost()+1;
    }
}
// 具体装饰者2
public class SausageDecorator extends AbstractDecorator{
    //父类没无参构造器了
    public SausageDecorator(ABattercake aBattercake) {
        super(aBattercake);
    }
    @Override
    protected void doSomething() {
    }
    @Override
    protected String getDesc() {
        return super.getDesc()+" 加一根香肠";
    }
    @Override
    protected int cost() {
        return super.cost()+2;
    }
}

public class Test {

    public static void main(String[] args) {
        ABattercake aBattercake;
        aBattercake = new Battercake();
        aBattercake = new EggDecorator(aBattercake);
        aBattercake = new EggDecorator(aBattercake);
        aBattercake = new SausageDecorator(aBattercake);
        System.out.println(aBattercake.getDesc() + " " + aBattercake.cost());
    }
}
//煎饼 加一个鸡蛋 加一个鸡蛋 加一根香肠:12

在这里插入图片描述
抽象的装饰者有没有必要,要看具体的业务场景,不是抽象的方法也没有关系,如果具体的装饰者必须要实现某个职责,可以用抽象的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值