装饰器模式-Java设计模式(四)

255 阅读5分钟

** 2019-12-04 12:36:55 **

装饰器模式-Java设计模式(四)

装饰器模式

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

适用范围

当系统中需要新加功能时,是向旧的类中添加新的代码。这些新的代码通常装饰了原有的核心职责或主要行为,在主类中加入新的字段,新的方法和逻辑,从而增加了主类的复杂度,而新的东西仅仅只是为了满足一些特定情况下才会执行的特殊行为需要。 ps:例如【LOL英雄/技能】【Pubg中枪/配件】

优缺点

优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。 缺点:多层装饰比较复杂。



代码 & 结构图(LOL)

【英雄】接口

/**
 * 英雄接口
 */
public interface Hero {
    /**
     * 学习技能
     */
    void learnSkills();
}

【具体英雄】类,实现英雄接口

/**
 * 具体英雄类,实现英雄接口
 * - 亚索
 */
public class Yasso implements Hero {

    /**
     * 英雄名称
     */
    private String name;

    public Yasso(String name) {
        this.name = name;
    }

    @Override
    public void learnSkills() {
        System.out.println(name + "学习了以上技能。");
    }
    
}

【技能栏】类,实现英雄接口

/**
 * 技能栏类,实现英雄接口
 */
public class Skills implements Hero {

    private Hero hero;

    public Skills(Hero hero) {
        this.hero = hero;
    }

    @Override
    public void learnSkills() {
        if (hero != null) {
            hero.learnSkills();
        }
    }
}

【技能】QWER类,继承技能栏类

/**
 * 技能Q ,继承技能栏类
 */
public class Q extends Skills {

    private String skillName;

    public Q(Hero hero, String skillName) {
        super(hero);
        this.skillName = skillName;
    }

    @Override
    public void learnSkills() {
        System.out.println("学习了技能Q:" + skillName);
        super.learnSkills();
    }
    
}

/**
 * 技能W ,继承技能栏类
 */
public class W extends Skills {

    private String skillName;

    public W(Hero hero, String skillName) {
        super(hero);
        this.skillName = skillName;
    }
    
    @Override
    public void learnSkills() {
        System.out.println("学习了技能W:" + skillName);
        super.learnSkills();
    }
}

/**
 * 技能E ,继承技能栏类
 */
public class E extends Skills {

    private String skillName;

    public E(Hero hero, String skillName) {
        super(hero);
        this.skillName = skillName;
    }

    @Override
    public void learnSkills() {
        System.out.println("学习了技能E:" + skillName);
        super.learnSkills();
    }
}

/**
 * 技能R ,继承技能栏类
 */
public class R extends Skills {

    private String skillName;

    public R(Hero hero, String skillName) {
        super(hero);
        this.skillName = skillName;
    }

    @Override
    public void learnSkills() {
        System.out.println("学习了技能R:" + skillName);
        super.learnSkills();
    }
}

【技能】测试

public class Test {
    public static void main(String[] args) {
        // 创建叫亚索的英雄
        Hero yasso = new Yasso("亚索");

        Skills skills = new Skills(yasso);
        
        Skills q = new Q(skills, "斩钢闪");
        q.learnSkills();
        System.out.println("-----1------分割线----------");
        Skills e = new E(q, "风盾");
        e.learnSkills();
        System.out.println("-----2------分割线----------");
        Skills w = new W(e, "踏前斩");
        w.learnSkills();
        System.out.println("-----3------分割线----------");
        Skills r = new R(w, "狂风绝熄斩");
        r.learnSkills();
        System.out.println("-----4------分割线----------");
        
    }
}

测试输出

UML结构图



代码 & 结构图(Pubg)

【枪】

【枪】接口

/**
 * 枪接口
 */
public interface Gun {
    /**
     * 开火
     */
    void fire();
}

【具体枪】类,继承枪接口

/**
 * M416类,实现枪接口
 */
public class M416 implements Gun {
    @Override
    public void fire() {
        System.out.println("突突突···开火*30");
    }
}

【扩容弹夹】

【扩容弹夹】抽象类,继承枪接口

/**
 * 扩容弹夹抽象类,实现枪接口
 */
public abstract class AbstractMagazine implements Gun {

    private Gun gun;

    public AbstractMagazine(Gun gun) {
        this.gun = gun;
    }

    @Override
    public void fire() {
        gun.fire();
    }
}

【扩容弹夹】实现类,继承扩容弹夹抽象类

/**
 * 扩容弹夹实现类,继承扩容弹夹抽象类
 */
public class Magazine extends AbstractMagazine {

    public Magazine(Gun gun) {
        super(gun);
    }

    @Override
    public void fire() {
        System.out.println("突突突···开火*40");
    }
}

【扩容弹夹】测试

public class Test {
    public static void main(String[] args) {
        System.out.println("【获取:M416】");
        Gun m416 = new M416();
        System.out.println("--------分割线---------");

        System.out.println("【上弹开火!】");
        m416.fire();
        System.out.println("--------分割线---------");

        System.out.println("【获取:扩容弹夹】");
        m416 = new Magazine(m416);
        m416.fire();
    }
}

测试输出


新增【4倍镜】

增加需求:【4倍镜】

这是之前没有的功能,新增接口Aim4X

/**
 * 4倍镜接口,实现枪接口
 */
public interface Aim4X extends Gun{
    void aim4X();
}

/**
 * 4倍镜抽象类,实现4倍镜接口
 */
public abstract class Abstract4X implements Aim4X {

    private Gun gun;

    public Abstract4X(Gun gun) {
        this.gun = gun;
    }

    @Override
    public void fire() {
        gun.fire();
    }

}

/**
 * 虚假的4倍镜类,继承4倍镜抽象类
 */
public class Ostensible4X extends Abstract4X {

    public Ostensible4X(Gun gun) {
        super(gun);
    }

    @Override
    public void aim4X() {
        System.out.println("装上了虚假的4倍,描边枪法。");
    }
}

/**
 * 真实的4倍镜类,继承4倍镜抽象类
 */
public class Real4X extends Abstract4X {

    public Real4X(Gun gun) {
        super(gun);
    }

    @Override
    public void aim4X() {
        System.out.println("装上了真实的4倍,突突突百发百中。");
    }
}

【4倍镜】测试

public class Test {
    public static void main(String[] args) {
        System.out.println("【获取:M416】");
        Gun m416 = new M416();
        System.out.println("--------分割线---------");

        System.out.println("【上弹开火!】");
        m416.fire();
        System.out.println("--------分割线---------");

        System.out.println("【获取:扩容弹夹】");
        m416 = new Magazine(m416);
        m416.fire();
        System.out.println("--------分割线---------");

        System.out.println("【获取:虚假的4倍】");
        // !!!注意!!!
        Aim4X aim4X = new Ostensible4X(m416);
        
        aim4X.aim4X();
        aim4X.fire();
        System.out.println("--------分割线---------");

        System.out.println("【获取:虚假的4倍】");
        aim4X = new Real4X(m416);
        aim4X.aim4X();
        aim4X.fire();
    }
}

测试输出


新增【8倍镜】

增加需求:【8倍镜】,它具有4倍瞄准功能,也具有8倍瞄准功能。

/**
 * 8倍接口,继承4倍接口
 */
public interface Aim8X extends Aim4X{
    void aim8X();
}

/**
 * 8倍抽象类,实现8倍接口
 */
public abstract class Abstract8X implements Aim8X {

    private Gun gun;

    public Abstract8X(Gun gun) {
        this.gun = gun;
    }

    @Override
    public void fire() {
        gun.fire();
    }
}

/**
 * 8倍类,继承8倍抽象类
 */
public class End8X extends Abstract8X {

    public End8X(Gun gun) {
        super(gun);
    }

    @Override
    public void aim4X() {
        System.out.println("8X--->4X");
    }

    @Override
    public void aim8X() {
        System.out.println("最终的8X");
    }
}

【8倍镜】测试

public class Test {
    public static void main(String[] args) {
        System.out.println("【获取:M416】");
        Gun m416 = new M416();
        System.out.println("--------分割线---------");

        System.out.println("【上弹开火!】");
        m416.fire();
        System.out.println("--------分割线---------");

        System.out.println("【获取:扩容弹夹】");
        m416 = new Magazine(m416);
        m416.fire();
        System.out.println("--------分割线---------");

        System.out.println("【获取:虚假的4倍】");
        // !!!注意!!!
        Aim4X aim4X = new Ostensible4X(m416);
        
        aim4X.aim4X();
        aim4X.fire();
        System.out.println("--------分割线---------");

        System.out.println("【获取:虚假的4倍】");
        aim4X = new Real4X(m416);
        aim4X.aim4X();
        aim4X.fire();
        System.out.println("--------分割线---------");

        System.out.println("【获取:8X】");
        // !!!注意!!!
        Aim8X aim8X = new End8X(aim4X);
        
        aim8X.aim8X();
        aim8X.aim4X();
        aim8X.fire();
        System.out.println("--------分割线---------");
    }
}

测试输出


UML图



源码 - decorator分支

不同分支对应不同设计模式源码 github.com/nullaman/Ja…

JDK中的例子

InputStream