设计模式学习之装饰器模式

装饰器模式,动态地给一个对象添加一些额外地职责,就增加功能方面来说,装饰器模式比生成子类更为灵活。装饰器模式是为已有功能动态地添加更多功能地一种方式。
但是我们什么时候可以使用装饰器模式呢?当系统需要新功能的时候,是向旧的类中添加新的代码。这些新加的代码通常装饰了原有类的核心职责或主要行为。这种做法的问题在于,在主类中加入了新的字段,新的方法和新的逻辑,从而增加了主类的复杂度,而这些新加入的东西仅仅是为了满足某种特定的场景需求。
装饰器模式提供了一个非常好的解决方案,把每个要装饰的功能放在单独的类中,并让这个类包装它所要装饰的对象,因此,当需要执行特殊行为是,客户代码就可以在运行是根据需要有选择地、按顺序地使用装饰功能包装对象了。
装饰器模式把类中的装饰功能从类中搬移去除,这样可以简化原有的类。有效地把类地核心职责和装饰功能区分开,并去除相关类中重复地装饰逻辑。

用一个简单的例子说明一下装饰器模式。男人爱帅,女人爱美。男人穿西装,打领带,穿皮鞋。女人穿裙子、戴耳环、穿高跟鞋。在这个例子中,男人和女人是需要装饰的对象,衣服、鞋以及耳环和领带是装饰品,用来装饰男人和女人。

类图如下:

实现代码如下:

/**
 * @author wgyang
 * Create time: 2020-04-13 23:27
 * Description:人物地基类
 */
public abstract class Person {
    /**
     * 人类会打扮自己
     */
    public abstract void dressUp();
}
/**
 * @author wgyang
 * Create time: 2020-04-13 23:34
 * Description:男人类(需要装饰地类)
 */
public class Man extends Person {
    @Override
    public void dressUp() {
        System.out.println("给男人打扮");
    }
}
/**
 * @author wgyang
 * Create time: 2020-04-13 23:35
 * Description:女人类(需要装饰地类)
 */
public class Woman extends Person {
    @Override
    public void dressUp() {
        System.out.println("给女人打扮");
    }
}
/**
 * @author wgyang
 * Create time: 2020-04-13 23:38
 * Description:
 */
public class Dress extends Person {

    private Person person;

    public void setPerson(Person person) {
        this.person = person;
    }

    @Override
    public void dressUp() {
        if (null != this.person) {
            this.person.dressUp();
        }
    }
}
/**
 * @author wgyang
 * Create time: 2020-04-13 23:46
 * Description: 耳环
 */
public class Earrings extends Dress {
    @Override
    public void dressUp() {
        super.dressUp();
        System.out.println("戴上耳环");
    }
}
/**
 * @author wgyang
 * Create time: 2020-04-13 23:47
 * Description: 高跟鞋
 */
public class HighHeeledShoes extends Dress {
    @Override
    public void dressUp() {
        super.dressUp();
        System.out.println("穿上高跟鞋");
    }
}
/**
 * @author wgyang
 * Create time: 2020-04-13 23:48
 * Description: 皮鞋
 */
public class LeatherShoes extends Dress {
    @Override
    public void dressUp() {
        super.dressUp();
        System.out.println("穿上皮鞋");
    }
}
/**
 * @author wgyang
 * Create time: 2020-04-13 23:44
 * Description: 领带
 */
public class Neckite extends Dress {
    @Override
    public void dressUp() {
        super.dressUp();
        System.out.println("打上领带");
    }
}
/**
 * @author wgyang
 * Create time: 2020-04-13 23:45
 * Description: 裙子
 */
public class Skirt extends Dress {
    @Override
    public void dressUp() {
        super.dressUp();
        System.out.println("穿上裙子");
    }
}
/**
 * @author wgyang
 * Create time: 2020-04-13 23:42
 * Description: 西装
 */
public class Suit extends Dress {
    @Override
    public void dressUp() {
        super.dressUp();
        System.out.println("穿上西装");
    }
}

客户端代码:

/**
 * @author wgyang
 * Create time: 2020-04-13 23:51
 * Description: 主类,分别给男人和女人穿上不同的服饰
 */
public class Main {
    public static void main(String[] args) {
        System.out.println("===============================");
        //先给男人装扮
        Man man = new Man();

        //男人穿西装,打领带,穿皮鞋
        Suit suit = new Suit();
        Neckite neckite = new Neckite();
        LeatherShoes leatherShoes = new LeatherShoes();

        //着装顺序:西装、领带、皮鞋
        leatherShoes.setPerson(neckite);
        neckite.setPerson(suit);
        suit.setPerson(man);
        leatherShoes.dressUp();
        System.out.println("===============================");

        //再给女人装扮
        Woman woman = new Woman();

        //女人穿裙子,戴耳环,穿高跟鞋
        Skirt skirt = new Skirt();
        Earrings earrings = new Earrings();
        HighHeeledShoes highHeeledShoes = new HighHeeledShoes();

        //着装顺序:裙子、耳环、高跟鞋
        highHeeledShoes.setPerson(earrings);
        earrings.setPerson(skirt);
        skirt.setPerson(woman);
        highHeeledShoes.dressUp();
        System.out.println("===============================");

        System.out.println("皮一下,给男人穿上裙子、戴上耳环、穿上高跟鞋");
        skirt.setPerson(man);
        highHeeledShoes.dressUp();
        System.out.println("===============================");
    }
}

运行结果如下:

===============================
给男人打扮
穿上西装
打上领带
穿上皮鞋
===============================
给女人打扮
穿上裙子
戴上耳环
穿上高跟鞋
===============================
皮一下,给男人穿上裙子、戴上耳环、穿上高跟鞋
给男人打扮
穿上裙子
戴上耳环
穿上高跟鞋
===============================

装饰器模式起作用的点在具体的装饰类在复写方法中调用父类同样的方法的地方,目前能想到的是在日志上的使用。其他方面的应用暂时还没想到,以后遇到再做上记录。

猜你喜欢

转载自www.cnblogs.com/wgyang/p/12702500.html