当前位置: 移动技术网 > IT编程>软件设计>设计模式 > 设计模式第三篇-装饰者模式

设计模式第三篇-装饰者模式

2018年12月25日  | 移动技术网IT编程  | 我要评论

一、引言

先看一个开发问题,很多人都玩过英雄联盟这款游戏:里面有各种英雄,每个英雄都有各自的技能(一般是4个主动技能),每升一级可以升级一个技能,但是可升级的技能不固定。我们需要通过技能状态来计算伤害,这个时候组合就非常多了(理论上是英雄数*技能数)。如果用继承来解决的话,那么子类就爆炸多了。

除了继承还有一种设计,就是在基类上增加布尔变量,如q,e等,然后提供一些has(get)和set方法来设置这些布尔值,子类里通过扩展计算伤害值,这个看起来是一个可行的设计,但这个设计也会有一些问题。

1.每个技能可以多次加点,单纯靠布尔值是处理不了的。

2.技能有可能会进行调整,那么我们就必须通过修改基类来处理。

3.游戏里面还有装备这种情况,增加装备也是相当于多了技能(貌似用装备来做例子更合适)。。。

我们用更好的方法来解决这个问题

这个问题的本质是扩展,我们想要扩展一些功能,但是不想用继承。装饰者模式可以解决这个问题

二、装饰者模式

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

意图:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。

主要解决:一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。

何时使用:在不想增加很多子类的情况下扩展类。

如何解决:将具体功能职责划分,同时继承装饰者模式。

装饰者通用类图:

 

三、实现

英雄联盟游戏实现

//抽象基类
public abstract class hero {
    //学习技能
    public abstract void learnskills();
}

//具体英雄兰博,需要被扩展的类
public class lanbo extends hero {
    //英雄属性
    private string name;

    public lanbo(string name){
        this.name = name;
    }
    @override
    public void learnskills() {
        system.out.println(name + "学习了以上技能!");
    }
}

//抽象技能类,装饰者的抽象基类
public abstract class skills extends hero {
    private hero hero;

    public skills(hero hero){
        this.hero = hero;
    }

    @override
    public void learnskills() {
        if(hero!=null){
            hero.learnskills();
        }
    }
}

//具体装饰子类,用来装饰 q技能
public class skill_q extends skills {
    private  string skillname;

    public skill_q(hero hero,string skillname) {
        super(hero);
        this.skillname=skillname;
    }
    @override
    public void learnskills() {
        system.out.println("学习了技能q:" +skillname);
        super.learnskills();
    }
}
//具体装饰子类,用来装饰 w技能
public class skill_w extends skills {
    private  string skillname;

    public skill_w(hero hero,string skillname) {
        super(hero);
        this.skillname=skillname;
    }
    @override
    public void learnskills() {
        system.out.println("学习了技能w:" +skillname);
        super.learnskills();
    }
}
//具体装饰子类,用来装饰e技能
public class skill_e extends skills {
    private  string skillname;
    public skill_e(hero hero,string skillname) {
        super(hero);
        this.skillname=skillname;
    }
    @override
    public void learnskills() {
        system.out.println("学习了技能e:" +skillname);
        super.learnskills();
    }
}
//具体装饰子类,用来装饰r技能
public class skill_r extends skills {
    private  string skillname;

    public skill_r(hero hero,string skillname) {
        super(hero);
        this.skillname=skillname;
    }
    @override
    public void learnskills() {
        system.out.println("学习了技能r:" +skillname);
        super.learnskills();
    }
}

运行:

        //选择英雄
        hero hero = new lanbo("兰博");
        skills q = new skill_q(hero,"纵火盛宴");
        skills w = new skill_w(q,"破碎护盾");
        skills e = new skill_e(w,"电子鱼叉");
        skills r = new skill_r(e,"恒温灼烧");
        //学习技能
        r.learnskills();

运行结果:

四、总结

优点

  1. 装饰这模式和继承的目的都是扩展对象的功能,但装饰者模式比继承更灵活
  2. 通过使用不同的具体装饰类以及这些类的排列组合,设计师可以创造出很多不同行为的组合
  3. 装饰者模式有很好地可扩展性

缺点:装饰者模式会导致设计中出现许多小对象,如果过度使用,会让程序变的更复杂。并且更多的对象会是的差错变得困难,特别是这些对象看上去都很像。

java.io类就是用的装饰者模式

 

 

 相关代码:

 

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网