设计模式 - 装饰模式

目录

引言

示例

代码

总结


引言

装饰模式。

顾名思义,装饰是什么?就是对某个东西进行修饰,从而使得某个东西具有更多的特性。

对应在java中,装饰的东西常常是一个类,对其进行装饰的目的是为了让它具有更多的属性和方法。然而实现这个目的却需要一种合理的方式。一般的思路是什么呢?

假设有一个接口Plant,该接口有一个实现类Tree。普通的树结的果子就是果子,但是有可能有些树结的果子是金子(。。。),比如摇钱树。实现树结出金子的方案有以下3种:

1、修改实现类Tree的方法。直接修改方法,突出一个不是树木共性的特性,这样不是很好;

2、再增加一个实现类,实现摇钱树。这样的话如果我想生成具有更多特性的树,岂不是需要生成很多实现类?

3、装饰模式,使用一个抽象类横向地扩展想要修饰的类(称为目标类)。这样不会影响目的类继承链上的其他类,例如:C extends B , B extends A,如果需要扩展B的功能,可以设计一个B的装饰类,它并不会影响B的子类C。如果采用在B里面增加方法,势必会使B的所有子类结构被改变。。


示例

装饰模式的一般步骤:

  • 定义一个接口Plant;
  • 定义一个装饰目标类Tree,实现接口Plant;
  • 定义一个用来装饰的横向扩展类(抽象类)TreeDecorator,内部持有目标类Tree的引用;
  • 定义一个横向扩展类的实现类TreeDecorator ,增强目标类想要增强的方法bearFruit();
  • 最后,客户端可以通过调用横向扩展类的实现类,来实现对Tree结出金子的方法,并且保证了不会影响Tree类的继承链上的其他类。

代码

接口:

public interface Plant {
    
    // 定义一个结果的方法
    String bearFruit();
}

实现类Tree(目标类):

public class Tree implements Plant {

    // 针对这个方法,想对他进行加强
    @Override
    public String bearFruit() {
        return "树结果子";
    }
}

横向扩展的抽象类(装饰类):

public class AbstractDecorator implements Plant {
    // 持有目标类的引用
    private Plant plant;

    // 构造函数注入目标类
    // 注:模块间的依赖通过抽象的接口(Plant)产生,而不是通过实现类(Tree),符合依赖倒置原则
    public AbstractDecorator (Plant plant) {
        this.plant = plant;
    }

    // 调用目标类的方法
    @Override
    public String bearFruit(){
        return plant.bearFruit();
    }
}

值得注意的是:模块间的依赖通过抽象的接口(Plant)产生,而不是通过实现类(Tree),符合依赖倒置原则

装饰类的实现类:

public class TreeDecorator extends AbstractDecorator {

    public TreeDecorator(Plant plant) {
        super(plant);
    }

    //装饰类增加的功能
    private String money() {
        return "这是摇钱树,结金子!";
    }

    //增强了功能的bearFruit方法
    @Override
    public String bearFruit() {
        return super.bearFruit() + "," + money();
    }
}

客户端代码:

public class Client {

    public static void main(String[] args) {
        // 创建目标类
        Plant plant = new Tree();

        // 创建装饰类,添加目标类的引用
        Plant moneyTree = new TreeDecorator(plant);

        // 执行增强后的结果方法,bearFruit()
        System.out.println(moneyTree.bearFruit());
    }
}

运行结果:


树结果子,这是摇钱树,结金子!

 


总结

使用场景:

  • 替代继承,扩展一个类的功能
  • 动态的给一个对象添加功能,以及动态的撤销该功能

优点:

  • 动态扩展一个实现类的功能,在不需要添加功能的时候,可以撤销装饰。
  • 装饰类和被装饰类模块间,通过抽象产生依赖,不会相互耦合
  • 装饰模式替换继承,可以避免继承链的子类被影响

装饰模式与代理模式的区别

  • 装饰模式:侧重给一个实现类动态添加功能,不会对实现类的方法进行过滤拦截
  • 代理模式:侧重将一个实现类的功能,委托给代理类来处理,可以对实现类的方法进行过滤拦截(某种情况下,可能不执行实现类的方法)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值