【设计模式】慎用多层继承,不妨试试装饰器模式

引入

玩过足球模拟经营类游戏的朋友,应该了解如何管理球队。其中对球队球员的转会,买入卖出尤其重要。

我们来模拟一下这个场景,球队经理Manager需要对球队需要的各类球员进行管理,其中的一环是要分析球员转会市场价,假设不同类型的球员转会费是不同的。

我们抽象出一个运动员出来,运动员有各自的计算转会费TransferFee的方法;

其中足球运动员继承运动员

开始

球队经理想要了解足球运动员的市场价格情况,这一场景我们可以通过如下类图表示:

在这里插入图片描述

public class Player {
    public void transferFee() {
        System.out.println("-------综合计算运动员的平均身价-----");
    }
}

class FootballPlayer extends Player {
    @Override
    public void transferFee() {
        System.out.println("------这里是足球运动员的平均身价-----");
    }
}

class GoalFootballPlayer extends FootballPlayer {
    @Override
    public void transferFee() {
        super.transferFee();
        System.out.println("------进球狂魔,这一类球员的身价----------");
    }
}

Manager想要了解足球运动员和进球狂魔运动员分别是多少:

public class Manager {
    public static void main(String[] args) {
        Player player = new GoalFootballPlayer();
        player.transferFee();
    }
}

运行结果:

------这里是足球运动员的平均身价-----
----------进球狂魔这一类球员的身价----------

这个Manager比较有个性,他想要引进进球多还要长得帅的足球运动员,那我们就得再写一个HandsomeFootballPlayer继承GoalFootballPlayer

Manager还不满足,是土豪,想换成既会进球,又长得帅,护球像亨利的足球运动员,这种球员就是大帝,那就再来一个GodFootballPlayer继承自HandsomeFootballPlayer;

Manager又有想法了…

在这里插入图片描述

如果就这样一直装饰着运动员继承下去,类的数量激增,而且不易维护!!!

在面向对象的设计中,如果超过两层继承,你就应该想想是不是出设计问题了!

那像这种情况我们怎么处理呢?我们分析一下这个场景,会进球长得帅护球像亨利的足球运动员这些其实都是对运动员进行一种装饰,那么我们就可以定义一批专门负责装饰的类,然后根据实际情况来决定是否需要进行装饰。

升级版:

在这里插入图片描述
实现(为了方便,类写在同一个文件里了):

/**
 * 足球运动员的装饰器
 * @author 行百里者
 */
public class FootballPlayerDecorator extends Player {
    private Player player;

    public FootballPlayerDecorator(Player player) {
        this.player = player;
    }

    @Override
    public void transferFee() {
        this.player.transferFee();
    }
}

/**
 * 会进球的足球运动员装饰
 */
class GoalFootballPlayerDecorator extends FootballPlayerDecorator {

    public GoalFootballPlayerDecorator(Player player) {
        super(player);
    }

    @Override
    public void transferFee() {
        super.transferFee();
        System.out.println("-------进球狂魔这一类球员的身价y万欧---------");
    }
}

/**
 * 长得帅的足球运动员装饰
 */
class HandsomeFootballPlayerDecorator extends FootballPlayerDecorator {

    public HandsomeFootballPlayerDecorator(Player player) {
        super(player);
    }

    @Override
    public void transferFee() {
        super.transferFee();
        System.out.println("-------长得帅的足球员的身价z万欧---------");
    }
}

/**
 * 足球运动员中的大帝
 */
class GodFootballPlayerDecorator extends FootballPlayerDecorator {

    public GodFootballPlayerDecorator(Player player) {
        super(player);
    }

    @Override
    public void transferFee() {
        super.transferFee();
        System.out.println("-------我的护球像亨利,传说中的大帝,价值 +∞!!! ---------");
    }
}

调用:

public class Manager {
    public static void main(String[] args) {
        // 只看足球运动员
        Player player = new FootballPlayer();
        // 给足球运动员加个会进球的装饰
        player = new GoalFootballPlayerDecorator(player);
        // 再给加个长得帅的装饰
        player = new HandsomeFootballPlayerDecorator(player);
        // 再加个大帝的装饰
        player = new GodFootballPlayerDecorator(player);

        // 看加完装饰后的身价
        player.transferFee();
    }
}

加装饰也可以直接这样调用:

Player player = new GodFootballPlayerDecorator(new GoalFootballPlayerDecorator(new HandsomeFootballPlayerDecorator(new FootballPlayer())));
player.transferFee();

运行结果:

------足球运动员的平均身价x万欧-----
-------进球狂魔这一类球员的身价y万欧---------
-------长得帅的足球员的身价z万欧---------
-------我的护球像亨利,传说中的大帝,价值 +∞!!! ---------

如果我再加其他装饰是不是就很容易了,直接增加装饰类就OK了!这就是装饰器模式

总结

装饰器模式是对继承的有力补充,继承层次太多的话程序就变得不易维护,不好扩展了。

同时,你还要知道继承是静态地给类增加功能,而装饰模式则是动态地增加功能,在上面的那个例子中,我不想要GodFootballPlayerDecorator这层的封装很简单,直接在调用的时候去掉就可以了,如果用继承就必须修改程序。

总之,装饰模式的扩展性非常好,符合真香定理😁。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值