戏说模式之装饰者模式(游戏)

装饰者模式

定义

装饰者(Decorator)模式提供了一种方法,使得在不改变原有类的基础上可以动态的扩展一个对象的功能。即动态的将指着附加到对象上。

装饰者模式的特点

1、 装饰对象和被装饰对象实现了相同的接口。客户端可以不加区分的使用具体是装饰者实现还是被装饰者实现的接口中的方法。

2、装饰对象有一个被装饰对象的实例。这样客户端就可以把被装饰对象的实例委托给装饰对象进行数据加工。

3、装饰对象被创建后,用创建后对象的实例调用接口方法,第一次方法的实现是在被装饰对象内完成。

4、客户端调用装饰对象无先后顺序。

具体场景案例

我们都玩过游戏。游戏中表现人物的情况一般都是用一堆属性来表示,如防御力、攻击力、速度等等。拿网游来举例,刚注册游戏时会让我们选择一个具体的角色(法师,弓箭手,武士等),进入游戏后游戏公司一般会赠送几件入门的装备(长剑,法杖,弓箭,鞋子等)。游戏的人物可以自由搭配各种装备。游戏中具体装备的搭配是有限制的如法师不能使用长剑、弓箭,武士不能使用弓箭、法杖等。为了方便描述在我们这个例子里就不做限制了,同时攻击也不再区分魔法攻击、物理攻击了。

在游戏这个场景中,我们就可以认为具体的角色(法师,弓箭手,武士等)就是被装饰对象,而装备(长剑,法杖,弓箭,鞋子等)就是装饰对象。

如上图定义了IAttribute作为人物属性的接口。接口中定义了getDefense(获取防御力),getPower(获取攻击力) ,getDescribe(获取描述)三个基础方法。Mage(法师)、Sagittary(弓箭手)、Warrior(武士)直接实现IAttribute的三个具体的角色。定义了Equip作为装备的基础抽象类实现IAttribute接口。Shoe(鞋子)、Bow(弓箭)、Sword(剑)、Wand(法杖)作为具体装备继承自Equip抽象类。

实现代码

package decorator;
/**
 * 属性
 */
public interface IAttribute {

    //获取防御力方法
    public float  getDefense();

    //获取攻击力方法
    public float  getPower();

    //获取描述
    public String getDescribe();
}
package decorator.role;
import decorator.IAttribute;
/**
 * 法师
 */
public class Mage implements IAttribute {
    //防御力
    private float defense = 5f;
    //攻击力
    private float power = 40f;
    //描述
    private String describe = "法师";

    @Override
    public String getDescribe() {
        return describe;
    }

    @Override
    public float getPower() {
        return power;
    }

    @Override
    public float getDefense() {
        return defense;
    }
}
package decorator.role;

import decorator.IAttribute;

/**
 * 弓箭手
 */
public class Sagittary implements IAttribute {
    //防御力
    private float defense = 10f;
    //攻击力
    private float power = 30f;
    //描述
    private String describe = "弓箭手";

    @Override
    public String getDescribe() {
        return describe;
    }

    @Override
    public float getPower() {
        return power;
    }

    @Override
    public float getDefense() {
        return defense;
    }
}
package decorator.role;

import decorator.IAttribute;

/**
 * 武士
 */
public class Warrior implements IAttribute {
    //防御力
    private float defense = 20f;
    //攻击力
    private float power = 20f;
    //描述
    private String describe = "武士";

    @Override
    public String getDescribe() {
        return describe;
    }

    @Override
    public float getPower() {
        return power;
    }

    @Override
    public float getDefense() {
        return defense;
    }
}
package decorator.equip;

import decorator.IAttribute;

/**
 * 装备基础类
 */
public abstract class Equip implements IAttribute {
    protected IAttribute attribute;
}
package decorator.equip;

import decorator.IAttribute;

/**
 * 鞋子
 */
public class Shoe extends Equip {
    private float defense = 70;
    private float power = 10;
    private String describe = "鞋子";
    public Shoe(IAttribute attribute){
        super.attribute = attribute;
    }
    @Override
    public float getDefense() {
        return super.attribute.getDefense() + defense;
    }

    @Override
    public float getPower() {
        return super.attribute.getPower() + power;
    }

    @Override
    public String getDescribe() {
        return super.attribute.getDescribe() + ","+describe;
    }
}
package decorator.equip;

import decorator.IAttribute;

/**
 * 弓
 */
public class Bow extends Equip {
    private float defense = 5;
    private float power = 50;
    private String describe = "弓箭";
    public Bow(IAttribute attribute){
        super.attribute = attribute;
    }
    @Override
    public float getDefense() {
        return super.attribute.getDefense() + defense;
    }

    @Override
    public float getPower() {
        return super.attribute.getPower() + power;
    }

    @Override
    public String getDescribe() {
        return super.attribute.getDescribe() + describe +",";
    }
}
package decorator.equip;

import decorator.IAttribute;

/**
 * 剑
 */
public class Sword extends Equip {
    private float defense = 20;
    private float power = 40;
    private String describe = "剑";
    public Sword(IAttribute attribute){
        super.attribute = attribute;
    }
    @Override
    public float getDefense() {
        return super.attribute.getDefense() + defense;
    }

    @Override
    public float getPower() {
        return super.attribute.getPower() + power;
    }

    @Override
    public String getDescribe() {
        return super.attribute.getDescribe() + ","+ describe;
    }
}
package decorator.equip;

import decorator.IAttribute;

/**
 * 法杖
 */
public class Wand extends Equip {
    private float defense = 2;
    private float power = 90;
    private String describe = "法杖";
    public Wand(IAttribute attribute){
        super.attribute = attribute;
    }
    @Override
    public float getDefense() {
        return super.attribute.getDefense() + defense;
    }

    @Override
    public float getPower() {
        return super.attribute.getPower() + power;
    }

    @Override
    public String getDescribe() {
        return super.attribute.getDescribe() + ","+ describe;
    }
}
package decorator;

import decorator.equip.*;
import decorator.role.Mage;
import decorator.role.Sagittary;
import decorator.role.Warrior;
import org.junit.Test;

/**
 * 客户端调用方法
 */
public class test {

    @Test
    public void testDecorator(){
        //创建法师
        IAttribute attribute = new Mage();
        attribute = new Shoe(attribute);//鞋子
        attribute = new Wand(attribute);//法杖
        pringMsg(attribute);

        //创建弓箭手
        IAttribute attribute1 = new Sagittary();
        attribute1 = new Shoe(attribute1);//鞋子
        attribute1 = new Bow(attribute1);//弓
        pringMsg(attribute1);

        //创建战士
        IAttribute attribute2 = new Warrior();
        attribute2 = new Shoe(attribute2);//鞋子
        attribute2 = new Sword(attribute2);//剑
        pringMsg(attribute2);
    }

    private void pringMsg (IAttribute attribute){
        System.out.println("角色描述:"+attribute.getDescribe());
        System.out.println("防御力:"+attribute.getDefense());
        System.out.println("攻击力:"+attribute.getPower());
    }
}

装饰者模式优点

1、装饰对象的添加和撤除非常灵活,客户端可以动态的给被装饰对象添加装饰对象,而且添加的顺序没有要求。

2、客户端通过使用不同的装饰对象的排列组合,可以设计出多种行为的组合。

装饰者模式的缺点

1、装饰者模式需要给每个装饰对象建立一个类,当装饰者非常多则会建立很多的装饰着类,会带来程序的碎片化添加程序的复杂度。

2、装饰者模式非常灵活,这也同时意味着该模式也有着更加多的复杂性。

时间: 2025-01-17 11:16:34

戏说模式之装饰者模式(游戏)的相关文章

Java进阶篇设计模式之五-----外观模式和装饰器模式

前言 在上一篇中我们学习了结构型模式的适配器模式和桥接模式.本篇则来学习下结构型模式的外观模式和装饰器模式. 外观模式 简介 外观模式隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口.这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性. 简单的来说就是对外提供一个简单接口,隐藏实现的逻辑.比如常用电脑的电源键,我们只需按电源键,就可以让它启动或者关闭,无需知道它是怎么启动的(启动CPU.启动内存.启动硬盘),怎么关闭的(关闭硬盘.关闭内存.关闭CPU)

IOS设计模式之二(门面模式,装饰器模式)

本文原文请见:http://www.raywenderlich.com/46988/ios-design-patterns. 由 @krq_tiger(http://weibo.com/xmuzyq)翻译,如果你发现有什么错误,请与我联系谢谢. 门面(Facade)模式(译者注:facade有些书籍译为门面,有些书籍译为外观,此处译为门面) 门面模式针对复杂的子系统提供了单一的接口,不需要暴漏一些列的类和API给用户,你仅仅暴漏一个简单统一的API. 下面的图解释了这个概念: 这个API的使用者

代理模式与装饰器模式的区别

代理模式与装饰器模式的区别,主要大于,从使用者(客户端)的角度来看的: //装饰器的客户public class Client{ public static void main(String[] args){ //客户指定了装饰者需要装饰的是哪一个类 Component component = new Decorator(new ConcreteComponent()); - }}//代理的客户public class Client{ public static void main(String

设计模式回顾:策略模式、代理模式、装饰者模式的区别

前言 设计模式有很多,但设计模式的目的是一致的,都是为了提升代码的可读性和可扩展性.设计模式都遵循一些基本的原则,设计模式是为了遵循这些原则而创造的工具. - 单一职责原则:就一个类而言,应该仅有一个引起它变化的原因.这一点是说,如果有一些类过于臃肿,承担了过多的职责,就应当分解他. - 开放-封闭原则:软件实体(类.模块.函数等)应该可以扩展,但是不可修改.这一点是说,拒绝硬编码,拒绝直接修改原有代码. - 依赖倒转原则:高层模块不应该以来低层模块.两个都应该以来抽象.抽象不应该依赖细节.细节

Java 代理模式和装饰者模式的区别

装饰模式:以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案:代理模式:给一个对象提供一个代理对象,并有代理对象来控制对原有对象的引用: 装饰模式应该为所装饰的对象增强功能:代理模式对代理的对象施加控制,并不提供对象本身的增强功能 二者的实现机制确实是一样的,可以看到他们的实例代码重复是很多的.但就语义上说,这两者的功能是相反的,模式的一个重要作用是简化其他程序员对你程序的理解, 你在一个地方写装饰,大家就知道这是在增加功能,你写代理,大家就知道是在限制, 虽然代码很可能相同,但如果你

【设计者模式】装饰者模式

装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能. 我们通过下面的实例来演示装饰器模式的用法.其中,我们将把一个形状装饰上不同的颜色,同时又不改变形状类. 介绍 意图:动态地给一个对象添加一些额外的职责.就增加功能来说,装饰器模式相比生成子类更为灵活. 主要解决:一般的,我们为了扩展一个

php模式之装饰者模式学习

<?php //装饰器模式主要是两类对象--被装饰者和装饰器对象 //装饰器和被装饰者拥有一样的超类(接口) //外层装饰对象重写公共方法,并委托调用内层方法. interface Decorate  {    # code...    public function display();  }     class Person implements Decorate  {       public $name;       public function __construct($name)

java代理模式与装饰者模式

静态代理和装饰者模式的区别: 先来看一下装饰者模式的定义:装饰者模式动态地将责任附加到对象上.若要扩展功能,装饰者提供了比继承更有弹性的替代方案. 总结一下采用装饰者模式是为了增强或拓展原对象的功能. 而静态代理除了能够提供功能增强外(AOP增加日志监控等,但不提供原对象本身的增强功能)还通常起到了控制访问的作用. 另外装饰者模式适用于递归组合. 看见百度静态代理和装饰者模式的区别出来前几个博客实在是无力吐槽,连装饰者模式其实就是动态代理模式都有人说的出来.. 相关连接: https://sta

设计模式——代理模式与装饰器模式

代理模式 解决的问题:在直接访问对象时带来很大的开销.在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层. 代理模式就相当于Windows 里面的快捷方式,它并不实现什么功能,而只是在中间加以控制:而装饰器模式为了增强功能. Java中的典型示例:静态代理:hibernate中的session.load()方法:动态代理:SpringAOP 代码