前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【设计模式】慎用多层继承,不妨试试装饰器模式

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

作者头像
行百里er
发布2020-12-02 14:37:11
3450
发布2020-12-02 14:37:11
举报
文章被收录于专栏:JavaJourneyJavaJourney

引入

玩过足球模拟经营类游戏的朋友,应该了解如何管理球队。其中对球队球员的转会,买入卖出尤其重要。 我们来模拟一下这个场景,球队经理Manager需要对球队需要的各类球员进行管理,其中的一环是要分析球员转会市场价,假设不同类型的球员转会费是不同的。 我们抽象出一个运动员出来,运动员有各自的计算转会费TransferFee的方法; 其中足球运动员继承运动员

开始

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

代码语言:javascript
复制
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想要了解足球运动员和进球狂魔运动员分别是多少:

代码语言:javascript
复制
public class Manager {
    public static void main(String[] args) {
        Player player = new GoalFootballPlayer();
        player.transferFee();
    }
}

运行结果:

代码语言:javascript
复制
------这里是足球运动员的平均身价-----
----------进球狂魔这一类球员的身价----------

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

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

Manager又有想法了...

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

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

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

升级版:

实现(为了方便,类写在同一个文件里了):

代码语言:javascript
复制
/**
 * 足球运动员的装饰器
 * @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("-------我的护球像亨利,传说中的大帝,价值 +∞!!!---------");
    }
}

调用:

代码语言:javascript
复制
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();
    }
}

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

代码语言:javascript
复制
Player player = new GodFootballPlayerDecorator(new GoalFootballPlayerDecorator(new HandsomeFootballPlayerDecorator(new FootballPlayer())));
player.transferFee();

运行结果:

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

大功告成!

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

总结

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

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

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

熬夜不易,欢迎关注、点赞、在看,给个鼓励,谢谢大伙! 也欢迎多踩踩我的博客:https://blog.csdn.net/hundred_li_journey

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-08-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 行百里er 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 引入
  • 开始
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档