java装饰器模式

本文介绍装饰器模式的概念、优点及应用场景,并通过实例说明如何利用该模式动态地为对象添加职责,增强功能的同时保持代码的灵活性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、装饰器模式定义
1、动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活
在这里插入图片描述
Component抽象构件

Component是一个接口或者是抽象类,就是定义我们最核心的对象,也就是最原始的对象,定义一个对象接口可以给这些对象动态地添加职责
ConcreteComponent 具体构件
ConcreteComponent是最核心、最原始、最基本的接口或抽象类的实现,需要装饰的就是它Decorator装饰角色

一般是一个抽象类,在它的属性里必然有一个private变量指向Component抽象构件。

具体装饰角色
ConcreteDecoratorA和ConcreteDecoratorB是两个具体的装饰类,要把最核心的、最原始的、最基本的东西装饰成其他东西

/**
 * 抽象构件
 */
public abstract class Componet {
    /**
     * 抽象方法
     */
    public abstract void operate();
}

/**
 * 具体构件
 */
public class ConcreteComponet extends Componet {
    @Override
    public void operate() {
        //具体的实现
        System.out.println("do something");
    }
}

/**
 * 装饰类
 */
public class Decorator extends Componet {
    private Componet componet = null;

    /**
     * 通过构造函数传递被修饰者
     *
     * @param componet
     */
    public Decorator(Componet componet) {
        this.componet = componet;
    }

    /**
     * 委托给被修者执行
     */
    @Override
    public void operate() {
        this.componet.operate();
    }
}
/**
 * 具体的装饰类
 */
public class ConcreteDecoratorA extends Decorator {
    /**
     * 通过构造函数传递被修饰者
     *
     * @param componet
     */
    public ConcreteDecoratorA(Componet componet) {
        super(componet);
    }

    /**
     * 定义自己的修饰方法
     */
    private void method1() {
        System.out.println("修饰DecoratorA");
    }

    @Override
    public void operate() {
        this.method1();
        super.operate();
    }
}
/**
 * 具体的装饰类
 */
public class ConcreteDecoratorB extends Decorator {

    /**
     * 通过构造函数传递被修饰者
     *
     * @param componet
     */
    public ConcreteDecoratorB(Componet componet) {
        super(componet);
    }

    /**
     * 定义自己的修饰方法
     */
    private void method2() {
        System.out.println("修饰方法DecoratorB");
    }

    @Override
    public void operate() {
        //重写父类的operate方法
        this.method2();
        super.operate();
    }
}
public class Client {
    public static void main(String[] args) {
        Componet componet = new ConcreteComponet();
        //第一次修饰
        componet = new ConcreteDecoratorA(componet);
        //第二次修饰
        componet= new ConcreteDecoratorB(componet);
        //修饰后运行
        componet.operate();
    }
}

煎饼有基础套餐,另外可以加鸡蛋,加菜等,可以用装饰模式表示

/**
 * 煎饼,抽象构建
 */
public abstract class Pancake {
    /**
     * 套餐
     * @return
     */
    public abstract String getMsg();

    /**
     * 价格
     * @return
     */
    public abstract Integer getPrice();
}
/**
 * 具体套餐
 */
public class BasicsPancake extends Pancake {
    @Override
    public String getMsg() {
        return "一张煎饼";
    }

    @Override
    public Integer getPrice() {
        return 3;
    }
}
/**
 * 加鸡蛋
 */
public class EggDecorator extends PancakeDecorator{
    /**
     * 通过构造函数传递被修饰者
     *
     * @param pancake
     */
    public EggDecorator(Pancake pancake) {
        super(pancake);
    }

    @Override
    public String getMsg() {
        return super.getMsg()+"加1个鸡蛋";
    }

    @Override
    public Integer getPrice() {
        return super.getPrice()+2;
    }
}
/**
 * 加蔬菜
 */
public class GreensDecorator extends PancakeDecorator{
    /**
     * 通过构造函数传递被修饰者
     *
     * @param pancake
     */
    public GreensDecorator(Pancake pancake) {
        super(pancake);
    }

    @Override
    public String getMsg() {
        return super.getMsg()+"加1份生菜";
    }

    @Override
    public Integer getPrice() {
        return super.getPrice()+1;
    }
}

public class Client {
    public static void main(String[] args) {
        Pancake basicsPancake = new BasicsPancake();
        basicsPancake = new EggDecorator(basicsPancake);
        basicsPancake = new GreensDecorator(basicsPancake);
        //一张煎饼加1个鸡蛋加1份生菜:价钱:6
        System.out.println(basicsPancake.getMsg() +":价钱:"+ basicsPancake.getPrice());
    }
}

二、装饰模式的优点
1、装饰类和被装饰类可以独立发展,而不会相互耦合。换句话说,Component类无须知道Decorator类,Decorator类是从外部来扩展Component类的功能,而Decorator也不用知道具体的构件
2、装饰模式是继承关系的一个替代方案。我们看装饰类Decorator,不管装饰多少层,返回的对象还是Component,实现的还是is-a的关系
3、装饰模式可以动态地扩展一个实现类的功能
三、装饰模式的缺点
多层的装饰是比较复杂的,就像剥洋葱一样,你剥到了最后才发现是最里层的装饰出现了问题
四、例子
在这里插入图片描述

●抽象构件(Component)角色:由InputStream扮演。这是一个抽象类,为各种子类型提供统一的接口。

●具体构件(ConcreteComponent)角色:由ByteArrayInputStream、FileInputStream、PipedInputStream、StringBufferInputStream等类扮演。它们实现了抽象构件角色所规定的接口。

●抽象装饰(Decorator)角色:由FilterInputStream扮演。它实现了InputStream所规定的接口。

●具体装饰(ConcreteDecorator)角色:由几个类扮演,分别是BufferedInputStream、DataInputStream以及两个不常用到的类LineNumberInputStream、PushbackInputStream。
四、使用场景
1、需要扩展一个类的功能,或给一个类增加附加功能。

2、需要动态地给一个对象增加功能,这些功能可以再动态地撤销。
3、 需要为一批的兄弟类进行改装或加装功能,首选装饰模式。

五、与代理模式的区别
代理模式专注于对被代理对象的访问;
装饰器模式专注于对被装饰对象附加额外功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值