设计模式 装饰者模式 带你重回传奇世界

今天继续设计模式之旅,给大家带来装饰者模式,国际惯例,先看定义。

装饰者模式:若要扩展功能,装饰者提供了比集成更有弹性的替代方案,动态地将责任附加到对象上。

先简单描述下装饰者模式发挥作用的地方,当我们设计好了一个类,我们需要给这个类添加一些辅助的功能,并且不希望改变这个类的代码,这时候就是装饰者模式大展雄威的时候了。这里还体现了一个原则:类应该对扩展开放,对修改关闭。

下面进入正题,今天在那看电影,忽然想起年轻时在游戏场上的血雨腥风啊,哈哈,下面以游戏为背景介绍装饰者模式。玩过游戏的兄弟应该都知道,游戏里面每个角色有武器、鞋子、护腕、戒指、还有各种红宝石、蓝宝石、黄宝石等等。

下面需求开始:设计游戏的装备系统,基本要求,要可以计算出每种装备在镶嵌了各种宝石后的攻击力和描述:

具体需求:

1、武器(攻击力20) 、戒指(攻击力5)、护腕(攻击力5)、鞋子(攻击力5)

2、蓝宝石(攻击力5/颗)、黄宝石(攻击力10/颗)、红宝石(攻击力15/颗)

3、每个装备可以随意镶嵌3颗

好了,需求介绍完毕,当然了,不要吐槽我的设计,尼玛鞋子哪来的攻击力,关键时刻也是可以砸人的嘛。下面开始初步的设想,出于多年面向对象的经验,我们可能会这么设计:

如果你这么设计了,我靠,就这么点需求你写了几百个类,随便添加两个宝石,哈哈,指数增长听过么,准备加班吧。

可能你还会这么设计:写一个超类,然后里面各种set宝石,然后在计算攻击力的地方,使劲的If有哪几种宝石,恭喜你,代码量不是很大,但是随便添加个武器,你得又多写多少个IF呢。

上面叙述了一些可能性的设计,都不是很好,下面看看如何将装饰者模式融入:

首先是装备的超类

package com.zhy.pattern.decorator;

/**
 * 装备的接口
 *
 * @author zhy
 *
 */
public interface IEquip
{

    /**
     * 计算攻击力
     *
     * @return
     */
    public int caculateAttack();

    /**
     * 装备的描述
     *
     * @return
     */
    public String description();
}

然后分别是武器、戒指、护腕、鞋子

package com.zhy.pattern.decorator;

/**
 * 武器
 * 攻击力20
 * @author zhy
 *
 */
public class ArmEquip implements IEquip
{

    @Override
    public int caculateAttack()
    {
        return 20;
    }

    @Override
    public String description()
    {
        return "屠龙刀";
    }

}
package com.zhy.pattern.decorator;

/**
 * 戒指
 * 攻击力 5
 * @author zhy
 *
 */
public class RingEquip implements IEquip
{

    @Override
    public int caculateAttack()
    {
        return 5;
    }

    @Override
    public String description()
    {
        return "圣战戒指";
    }

}
package com.zhy.pattern.decorator;

/**
 * 护腕
 * 攻击力 5
 * @author zhy
 *
 */
public class WristEquip implements IEquip
{

    @Override
    public int caculateAttack()
    {
        return 5;
    }

    @Override
    public String description()
    {
        return "圣战护腕";
    }

}
package com.zhy.pattern.decorator;

/**
 * 鞋子
 * 攻击力 5
 * @author zhy
 *
 */
public class ShoeEquip implements IEquip
{

    @Override
    public int caculateAttack()
    {
        return 5;
    }

    @Override
    public String description()
    {
        return "圣战靴子";
    }

}

接下来当然是装饰品,宝石了,首先超类

package com.zhy.pattern.decorator;

/**
 * 装饰品的接口
 * @author zhy
 *
 */
public interface IEquipDecorator extends IEquip
{

}

下来蓝宝石、黄宝石、红宝石

package com.zhy.pattern.decorator;

/**
 * 蓝宝石装饰品
 * 每颗攻击力+5
 * @author zhy
 *
 */
public class BlueGemDecorator implements IEquipDecorator
{
    /**
     * 每个装饰品维护一个装备
     */
    private IEquip equip;

    public BlueGemDecorator(IEquip equip)
    {
        this.equip = equip;
    }

    @Override
    public int caculateAttack()
    {
        return 5 + equip.caculateAttack();
    }

    @Override
    public String description()
    {
        return equip.description() + "+ 蓝宝石";
    }

}
package com.zhy.pattern.decorator;

/**
 * 黄宝石装饰品
 * 每颗攻击力+10
 * @author zhy
 *
 */
public class YellowGemDecorator implements IEquipDecorator
{
    /**
     * 每个装饰品维护一个装备
     */
    private IEquip equip;

    public YellowGemDecorator(IEquip equip)
    {
        this.equip = equip;
    }

    @Override
    public int caculateAttack()
    {
        return 10 + equip.caculateAttack();
    }

    @Override
    public String description()
    {
        return equip.description() + "+ 黄宝石";
    }

}
package com.zhy.pattern.decorator;

/**
 * 红宝石装饰品 每颗攻击力+15
 *
 * @author zhy
 *
 */
public class RedGemDecorator implements IEquipDecorator
{
    /**
     * 每个装饰品维护一个装备
     */
    private IEquip equip;

    public RedGemDecorator(IEquip equip)
    {
        this.equip = equip;
    }

    @Override
    public int caculateAttack()
    {
        return 15 + equip.caculateAttack();
    }

    @Override
    public String description()
    {
        return equip.description() + "+ 红宝石";
    }

}

好了,到此结束,我们已经实现了需求的功能了,是不是每个类都很清晰加简单,下面看测试:

package com.zhy.pattern.decorator;

public class Test
{
    public static void main(String[] args)
    {
        // 一个镶嵌2颗红宝石,1颗蓝宝石的靴子
        System.out.println(" 一个镶嵌2颗红宝石,1颗蓝宝石的靴子");
        IEquip equip = new RedGemDecorator(new RedGemDecorator(new BlueGemDecorator(new ShoeEquip())));
        System.out.println("攻击力  : " + equip.caculateAttack());
        System.out.println("描述 :" + equip.description());
        System.out.println("-------");
        // 一个镶嵌1颗红宝石,1颗蓝宝石的武器
        System.out.println(" 一个镶嵌1颗红宝石,1颗蓝宝石,1颗黄宝石的武器");
        equip = new RedGemDecorator(new BlueGemDecorator(new YellowGemDecorator(new ArmEquip())));
        System.out.println("攻击力  : " + equip.caculateAttack());
        System.out.println("描述 :" + equip.description());
        System.out.println("-------");
    }
}

输出:

 一个镶嵌2颗红宝石,1颗蓝宝石的靴子
攻击力  : 40
描述 :圣战靴子+ 蓝宝石+ 红宝石+ 红宝石
-------
 一个镶嵌1颗红宝石,1颗蓝宝石,1颗黄宝石的武器
攻击力  : 50
描述 :屠龙刀+ 黄宝石+ 蓝宝石+ 红宝石
-------

赞不赞,要是需求随便多几个装备,几种宝石,我们随随便便就可以加上,然后开开心心下班。

好了,恭喜你,你又学会了一个设计模式,装饰者模式。

现在根据例子对定义的理解,不用我多说吧。

Java的API中也有装饰者模式的身影,如果你初学Java,一定记得Java里面的各种流,很痛苦吧,但是当你明

白你们的设计之后就会感觉清晰很多。

把InputStream看作我们的IEquip,把FilterInputStream看作我们的IEquipDecorator,是不是和我们的设计几乎一样~

好了,就到这里,编程也是很有乐趣的么~是吧,各位看官留个言、给个赞呗~

源码点击下载

时间: 2024-10-20 20:20:32

设计模式 装饰者模式 带你重回传奇世界的相关文章

5分钟读书笔记之 - 设计模式 - 装饰者模式

本章讨论的是一种为对象增添特性的技术,它并不使用创建新子类这种手段. 装饰者模式可以透明地把对象包装在具有同样接口的另一对象之中,这样一来,你可以给一些方法添加一些行为,然后将方法调用传递给原始对象.相对于创建子类来说,使用装饰者模式对象是一种更灵活的选择. 装饰者可用于为对象增加功能.它可以用来替代大量子类. 考虑前面的自行车类,你现在可能提供一些配件供用户选择,装饰者模式要求我们只需要创建选件类,这些类与四种自行车类都要实现Bicycle接口,但是他们只被用作这些自行车类的包装类.在这个例子

【笔记】设计模式——装饰者模式

实现一个类似QQavator功能的代码 1.原始实现 1 //存在的问题: 2 //1.wear*方法出现重复代码,可以重构:实质上为代码结构一致,输出内容相同,可以通过在定义一个基类,在基类中定义抽象的Wear*,在子类中重写: 3 //2.倘若需求中新增某种服饰,需要修改Person类代码,不符合开放--封闭原则: 4 //3.客户端中代码暴露了具体装饰细节,理想情况下只需要提供装饰顺序,装饰细节封装起来: 5 class Person 6 { 7 private string name;

设计模式 - 装饰者模式(Decorator Pattern) Java的IO类 使用方法

装饰者模式(Decorator Pattern) Java的IO类 使用方法 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26716823 装饰者模式(decorator pattern)参见: http://blog.csdn.net/caroline_wendy/article/details/26707033 Java的IO类使用装饰者模式进行扩展, 其中FilterInputStream类, 就是装饰者(decora

java设计模式------装饰着模式

java设计模式-------装饰者模式 装饰者模式 Decorator模式(别名Wrapper):动态将职责附加到对象上,若要扩展功能,装饰者提供了比继承更具弹性的代替方案.主要有组件(components)和装饰器(Decorator)组成.要求components和Decorator实现相同的接口或者抽象类(具体类的局限性太大). 设计原则.模式特点.适用性 - 1. 多用组合,少用继承. 利用继承设计子类的行为,是在编译时静态决定的,而且所有的子类都会继承到相同的行为.然而,如果能够利用

设计模式---装饰者模式(学习笔记)

首先看装饰者模式的定义:动态的将责任附加到对象上.若要扩展功 能,装饰者提供了比继承更有弹性的替代方案! 先看看<大话设计模式>给出的类图: 实际上,装饰者模式就是:把装饰者对象当成"包装者",换言之,把要装饰的对象作为参数传递到装饰对象里去,然后进行操作.(如果理解不对,希望给指正),下面看代码来理解这个类图: 这是装饰者和需要装饰的具体对象共同的接口: public abstract class Component { abstract void Operation()

设计模式 - 装饰者模式(Decorator Pattern) 详解

装饰者模式(Decorator Pattern) 详解 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26707033 装饰者模式(Decorator Pattern):动态地将责任附加到对象上. 若要扩展功能, 装饰者提供了比继承更有弹性的替代方案. 使用方法: 1. 首先创建组件(Component)父类, 所有类,具体组件(Concrete Component)和装饰者(Decorator)都属于这一类型, 可以进行扩展

Java设计模式——装饰者模式

JAVA 设计模式 装饰者模式 用途 装饰者模式 (Decorator) 动态地给一个对象添加一些额外的职责.就增加功能来说,Decorator 模式相比生成子类更为灵活. 装饰者模式是一种结构式模式. 结构 图-装饰者模式结构图 Component : 定义一个对象接口,可以给这些对象动态地添加职责. interface Component {     public void operation(); } ConcreteComponent : 实现 Component 定义的接口. clas

说说设计模式~装饰器模式(Decorator)

装饰器模式,也叫又叫装饰者模式,顾名思义,将一个对象进行包裹,包装,让它变成一个比较满意的对象,这种模式在我们平时项目开发中,经常会用到,事实上,它是处理问题的一种技巧,也很好的扩展了程序,让程序代码不那么死板! 何时能用到它? 1. 需要扩展一个类的功能,或给一个类添加附加职责. 2. 需要动态的给一个对象添加功能,这些功能可以再动态的撤销. 3. 需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实. 4. 当不能采用生成子类的方法进行扩充时. 其中我们认为第四种

PHP设计模式-装饰器模式

1.概念: 装饰器模式又叫做装饰者模式,是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能.传统的编程模式都是子类继承父类实现方法的重载,使用装饰器模式,只需添加一个新的装饰器对象,更加灵活,避免类数目和层次过多. 2.角色: Component(被装饰对象基类):定义一个对象接口,以规范准备接受附加责任的对象. ConcreteComponent(具体被装饰对象):具体组件角色,即将要被装饰增加功能的类. Decorator(装饰者基类):装饰器接口. ConcreteDecor