设计模式 | 装饰者模式与继承的举例比较

区别

装饰者继承
优势代码灵活性高、耦合度低、扩展性强代码结构清晰、实现简单
缺陷大量使用多态维护实例使得代码稍复杂程序臃肿、子类爆炸

装饰器

IO中用的最多的就是装饰器模式~

  • 装饰器模式是什么:通过包装原有类来实现增强对象的一种设计模式
  • 装饰器模式作用: 在实现增强对象的前提下,避免程序臃肿,降低耦合度

使用场景

  1. 扩展一个类的功能。
  2. 动态增加功能,动态撤销
  3. 继承关系会出现过多子类时

示例

  • 先来一个Person接口
public interface Person {
    void eat();
}
  • 实现接口得到Man父类
public class Man implements Person{
    @Override
    public void eat() {
        System.out.println("吃饭...");
    }
}
  • 装饰ManSuperMan装饰(器)类
public abstract class SuperMan implements Person{
    private Person person;
    public SuperMan(Person person) {
        this.person = person;
    }
    @Override
    public void eat() {
        person.eat();
    }
}
  • 需求:不修改Man类的前提下,实现“吃饭”前要先“洗手
  • 用继承方式实现
  1. 第一步:继承Man类并增加洗手的方法
public class CleanMan extends Man{
    public void wash() {
        System.out.println("洗手...");
    }
    @Override
    public void eat(){
        wash();
        super.eat();
    }
}
  1. 第二步:创建对象调用增强后的方法
public static void main(String[] args) {
        // 创建对象
        Man cleanMan = new CleanMan();
        // 调用增强过的eat()方法
        cleanMan.eat();
    }

结果:

洗手…
吃饭…

  • 用装饰器实现
  1. 第一步:继承Man的装饰类
public class CleanSuperMan extends SuperMan{
    public CleanSuperMan(Person person) {
        super(person);
    }
    // 扩展功能
    public void wash() {
        System.out.println("洗手...");
    }
    // 实现吃饭前先洗手
    @Override
    public void eat() {
        wash();
        super.eat();
    }
}
  1. 第二步:创建对象并装饰
public class Mian {
    public static void main(String[] args) {
        // 原本实现类
        Person man = new Man();
        // 装饰他
        man = new CleanSuperMan(man);
        man.eat();
    }
}

结果:

洗手…
吃饭…

  • 上面的例子通过继承装饰器模式都实现了对象功能的增强,甚至看起来装饰器模式还比继承麻烦许多。
  • 那么问题来了,我们何必要用装饰器?
  • 现在我们更换需求:“吃饭”前不“洗手”了

用装饰器实现

  • 不再装饰man对象就ok了
public class Mian {
    public static void main(String[] args) {
        // 原本实现类
        Person man = new Man();
        // 装饰他
        //man = new CleanSuperMan(man);
        man.eat();
    }
}

用继承实现

  • 在Man的子类CleanMan中去掉wash()方法的调用
public class CleanMan extends Man{
    public void wash() {
        System.out.println("洗手...");
    }
    @Override
    public void eat(){
        // wash();
        super.eat();
    }
}

差异

两种方式比较之下可以明显看出装饰者模式比继承灵活很多。
继承在改变需求时,要修改子类代码,这样就引出了一个问题,例如以上代码中不再需要wash()方法时,应该在增强后的类中完全去掉该方法,还是去掉它的调用?如果完全去掉那么后续需要时得重写,如果去掉调用,那么可能出现垃圾代码。而装饰者模式中,装饰器是独立于原本的代码之外的,由此可见,其大大解决了复杂的继承关系引起的子类爆炸问题。

IO中的装饰者模式

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new FileWriter("key.txt"));
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值