ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

设计模式-Decorator模式

2019-09-05 18:02:21  阅读:207  来源: 互联网

标签:getEquip getPrice return 装备 模式 gamer 设计模式 public Decorator


目录

Decorator(装饰器)模式属于结构型模式。
比如当其需要三种不同的附加特性,可以为其创建三个派生类。但是若它还需要同时具有其中两种特性或者是各种特性的任意组合的时候,类继承的方法就不再适合了。
它允许向一个现有的对象不通过继承来添加新的功能,同时又不改变其结构。

一个例子(贪玩蓝月)

前一阵子张家辉代言的《贪玩蓝月》广告火了,“我系喳喳辉,是兄弟就来砍我~”被洗脑到现在,正好用这个游戏来解释一下装饰器模式。

玩游戏的人都知道这种类传奇的游戏核心玩法就是买装备,打怪,升级,买装备这样反复。

刚注册账号进入游戏的玩家假设只有一条大裤衩,价值5金币,随着刷怪升级,身上的装备也在一件件增多,这时候我们需要知道身上的装备价值多少金币。

定义玩家

public interface Gamer {
    /**
     * 获取目前的装备
     * @return
     */
    String getEquip();

    /**
     * 获取目前身上装备的价格
     * @return
     */
    int getPrice();
}

定义具体的法师职业玩家

public class MasterGamer implements Gamer {
    /**
     * 获取目前的装备
     *
     * @return
     */
    @Override
    public String getEquip() {
        return "大裤衩";
    }

    /**
     * 获取目前身上装备的价格
     *
     * @return
     */
    @Override
    public int getPrice() {
        return 5;
    }
}

新法师玩家出门只有大裤衩,装备全靠打。

传统继承实现

装备“法师权杖”

public class TruncheonMasterGamer extends MasterGamer{
    /**
     * 获取目前的装备
     *
     * @return
     */
    @Override
    public String getEquip() {
        return super.getEquip()+",法师权杖";
    }

    /**
     * 获取目前身上装备的价格
     *
     * @return
     */
    @Override
    public int getPrice() {
        return super.getPrice()+50;
    }
}

继续装备“魔法斗篷”

public class CloakTruncheonMasterGamer extends TruncheonMasterGamer{
    /**
     * 获取目前的装备
     *
     * @return
     */
    @Override
    public String getEquip() {
        return super.getEquip()+",魔法斗篷";
    }

    /**
     * 获取目前身上装备的价格
     *
     * @return
     */
    @Override
    public int getPrice() {
        return super.getPrice()+80;
    }
}

注意,这里是在之前已经装备了“法师权杖”之上去继承。

计算装备价格

CloakTruncheonMasterGamer gamer = new CloakTruncheonMasterGamer();
System.out.println("当前装备:"+gamer.getEquip()+"\n装备总价值:"+gamer.getPrice());

输出结果

当前装备:大裤衩,法师权杖,魔法斗篷
装备总价值:135

装饰器模式实现

image
声明通用装饰器基类“装备”

public abstract class Equip implements Gamer {
    private Gamer gamer;

    public Equip(Gamer gamer) {
        this.gamer = gamer;
    }
    /**
     * 获取目前的装备
     *
     * @return
     */
    @Override
    public String getEquip() {
        return gamer.getEquip();
    }

    /**
     * 获取目前身上装备的价格
     *
     * @return
     */
    @Override
    public int getPrice() {
        return gamer.getPrice();
    }
}

具体装饰器“法师权杖”

public class Truncheon extends Equip {
    public Truncheon(Gamer gamer) {
        super(gamer);
    }

    /**
     * 获取目前的装备
     *
     * @return
     */
    @Override
    public String getEquip() {
        return super.getEquip()+",法师权杖";
    }

    /**
     * 获取目前身上装备的价格
     *
     * @return
     */
    @Override
    public int getPrice() {
        return super.getPrice()+50;
    }
}

具体装饰器“魔法斗篷”

public class Cloak extends Equip {
    public Cloak(Gamer gamer) {
        super(gamer);
    }

    /**
     * 获取目前的装备
     *
     * @return
     */
    @Override
    public String getEquip() {
        return super.getEquip()+",魔法斗篷";
    }

    /**
     * 获取目前身上装备的价格
     *
     * @return
     */
    @Override
    public int getPrice() {
        return super.getPrice()+80;
    }
}

计算装备价格

//创建一个法师玩家
Gamer gamer = new MasterGamer();
//给法师玩家装备法师权杖
gamer = new Truncheon(gamer);
//给法师玩家装备魔法斗篷
gamer = new Cloak(gamer);
System.out.println("当前装备:"+gamer.getEquip()+"\n装备总价值:"+gamer.getPrice());

输出结果

当前装备:大裤衩,法师权杖,魔法斗篷
装备总价值:135

对比

上面例子比较简单,传统继承实现和装饰器模式实现区别不是很明显,但仔细思考还是会发现一些区别:

  • 传统继承实现不自由,没有“组件化”特性。玩家的装备是可以随意组合,随意拆卸的,而这种特性对于继承来说只能通过各种各样的子类组合来实现。就像上面的例子,装备“法师权杖”和“魔法斗篷”需要在拥有“法师权杖”的基础上再去继承。
  • 装饰器模式实现,使得附属属性和主体分开,而又不单独存在(Equip类里面声明了Gamer对象)。装备和玩家是分开的,可以给玩家单独装备任何装备,也可以随意卸下装备。

总结

这种设计模式下不仅可以扩展一个类的功能,也可以动态增加功能,动态撤销。但缺点就是多层装饰使用起来相对比较复杂。本质是将具体功能职责划分(例如区分核心组件以及附加属性职责)减少子类直接继承父类的耦合性。


你可以在这里获取相关代码:设计模式-Decorator模式

标签:getEquip,getPrice,return,装备,模式,gamer,设计模式,public,Decorator
来源: https://www.cnblogs.com/xuxiaojian/p/11468734.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有