java设计模式-装饰器模式

装饰器模式(Decorator Pattern允许向一个现有的对象添加新的功能,同时又不改变其结构。(好比一个房子,可以添加一些家具,养一个宠物,而房子的整体结构是不变的)
Design Patterns - Elements of Reusable Object-Oriented Software(即:设计模式 可复用面向对象软件基础)书中介绍:
意图:动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。
别名:包装器Wrapper
优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
缺点:多层装饰比较复杂。
使用场景: 1、扩展一个类的功能。 2、动态增加功能,动态撤销。
适用性:

  1. 在不影响其他对象的情况下,以动态,透明的方式给单个对象添加职责
  2. 处理可以撤销的职责
  3. 当不采用生成子类的方式进行扩充时。一种情况是,可能有大量独立的扩展为支持,每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况是因为定义类被隐藏,或类定义不能用于生成子类.

实现
1.接口一致性:装饰对象的接口必须与他所装饰的Component(组件)的接口是一致的,即所有的ConcreteDecorator(具体装饰者)类必须有一个公共的父类
2. 省略抽象的Decorator类:当仅仅只需要添加一个职责时,没有必要定义一个抽象的Decorator类。通常只需要处理现存的类层次结构而不是设计一个新的系统,此时可以把Decorator向Component转发请求的职责合并到ConcreteDecorator中
3. 保持Component类的简单性:为了保证接口的一致性,组件和装饰必须有一个公共的Decorator父类。即它应集中于定义接口而不是存储数据,对数据表示的定义应延迟到子类中,否则Component类会变得过于复杂和庞大,因而难以大量使用。赋予Component太多的工能也使得,具体的子类有一些他们并不需要的工能的可能性大大增加
4. 改变对象外壳与改变对象内核:即将Decorator看做一个对象的外壳,它可以改变这个对象的行为。另一种方法是改变对象的内核。

1.Component 类充当抽象角色,不应该具体实现。
2、修饰类引用和继承 Component 类,具体扩展类重写父类方法
具体实现:
创建一个接口

public interface Box {

    public void goods();
}

创建一个实现Box接口的抽象装饰类

public abstract  class Decorator implements Box {

    public Box box;

    public Decorator(Box box) {
        this.box = box;
    }

    @Override
    public void goods() {
        box.goods();
    }
}

创建实现Box接口的实体类

public class January implements Box {

    private List<String> goods = new ArrayList<>();
    @Override
    public void goods() {
        goods.add("一本书");
        System.out.println("=======一月盒子里只有一本书=========");
    }

    public List<String> getGoods() {
        return goods;
    }

    public void setGoods(List<String> goods) {
        this.goods = goods;
    }
}

创建扩展Decorator类的实体装饰类

public class February extends Decorator{


    public February(Box box) {
        super(box);
    }

    public void buyMobilePhone(){
        January january = (January) box;
        january.getGoods().add("手机");
        System.out.println("======二月买了一个手机放进盒子里======");
    }

    @Override
    public void goods() {
        //一月的笔记本还在
        super.goods();
        buyMobilePhone();
    }
}

创建一个扩展February的实体装饰类

public class March extends February{

    public March(Box box) {
        super(box);
    }

    public void addLaptop(){
        January january = (January) box;
        january.getGoods().add("笔记本电脑");
        System.out.println("======三月买了笔记本电脑放进盒子里======");
    }

    @Override
    public void goods() {
        //在二月的基础上加了笔记本电脑
        super.goods();
        addLaptop();
    }
}

测试:

public class TestDecorator {

    public static void main(String[] args) {
        Box box = new January();
        System.out.println("======一月的盒子里面======");
        box.goods();
        System.out.println("======一月的盒子里面======\n");

        System.out.println("======二月的盒子里面======");
        Box f = new February(box);
        f.goods();
        System.out.println("======二月的盒子里面======\n");

        System.out.println("======三月的盒子里面======");
        Box m = new March(box);
        m.goods();
        System.out.println("======三月的盒子里面======\n");
    }
}

结果:

======一月的盒子里面======
=======一月盒子里只有一本书=========
======一月的盒子里面======

======二月的盒子里面======
=======一月盒子里只有一本书=========
======二月买了一个手机放进盒子里======
======二月的盒子里面======

======三月的盒子里面======
=======一月盒子里只有一本书=========
======二月买了一个手机放进盒子里======
======三月买了笔记本电脑放进盒子里======
======三月的盒子里面======
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值