装饰者模式案例(代码)讲解

设计模式的代码:https://github.com/Aerozb/design_patterns

参考:https://blog.csdn.net/cauchyweierstrass/article/details/48240147

装饰者模式中类或接口的作用:

抽象被装饰者:需要增加修饰的抽象对象。
具体被装饰者:定义一个将要接收附加责任的类。
装饰(Decorator)角色:持有一个抽象被装饰者对象的实例,并继承它
具体装饰(ConcreteDecorator)角色:负责给具体被装饰者“贴上”附加的责任。

模拟穿衣服场景

我们来看下面一个具体的案例:每个人一天起床之后都要穿衣服(来装饰自己),这是必不可少的,这样问题就来了,穿什么?按照什么顺序穿? 

/**
 * 模拟一个人穿衣服的过程
 * 抽象类,用来规范将要被附加一些操作的对象
 */
public abstract class People {
    public abstract void wear();
}
/**
 * 具体的对象,该对象将被附加一些额外的操作
 */
public class Jack extends People {
    @Override
    public void wear() {
        System.out.println("该穿什么衣服呢");
    }
}
/**
 * 装饰者类,持有一个将要被装饰者的接口对象实例
 */
public class Decorator extends People {

    public People people;

    //记得生成带参构造,用来给被装饰者赋值
    public Decorator(People people) {
        this.people = people;
    }

    @Override
    public void wear() {
        people.wear();
    }
}
/**
 * 具体的装饰者类,负责给增加附加的操作:穿衬衫
 */
public class DecoratorShirt extends Decorator {

    public DecoratorShirt(People people) {
        super(people);
    }

    public void  wear(){
        super.wear();
        System.out.println("穿衬衫");
    }
}
/**
 * 具体的装饰者类,负责给增加附加的操作:穿西服
 */
public class DecoratorSuit extends Decorator {

    public DecoratorSuit(People people) {
        super(people);
    }

    public void wear() {
        super.wear();
        System.out.println("穿个西服");
    }
}
public class Client {
    public static void main(String[] args) {
        People people =new DecoratorShirt(new DecoratorSuit(new Jack()));
        people.wear();
    }
}

 结果:

该穿什么衣服呢
穿个西服
穿衬衫
装饰者模式案例(代码)讲解_第1张图片 UML类图
蓝色实线代表继承
白色虚线依赖箭头指向被依赖对象
实线+菱形代表聚合

 

装饰者模式案例(代码)讲解_第2张图片

特点:

1.装饰对象和真实对象有相同的接口。这样客户端对象就能以和真实对象相同的方式和装饰对象交互。

2.装饰对象包含一个真实对象的引用(reference)

3.装饰对象接受所有来自客户端的请求。它把这些请求转发给真实的对象。

4.装饰对象可以在转发这些请求以前或以后增加一些附加功能。这样就确保了在运行时,不用修改给定对象的结构就可以在外部增加附加的功能。

适应性:

1.需要扩展一个类的功能,或给一个类添加附加职责。
2.需要动态的给一个对象添加功能,这些功能可以再动态的撤销。
3.需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实。
4.当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。

用户代码执行过程 

1.用户调用 People people =new DecoratorShirt(new DecoratorSuit(new Jack()));

都是new 最里面的,然后再new外面的,Decorator类继承又聚合了People抽象类,new DecoratorSuit(new Jack()),把Jack赋值给DecoratorSuit的属性之People类,相当于DecoratorSuit类拥有了一个Jack类

2.调用people.wear();

调用自己(DecoratorShirt)的wear,而自己的wear又调用了super.waer():就是调用属性people类的wear()方法,所以一层一层往里执行,执行到被装饰者的wear()后开发返回。

装饰者模式案例(代码)讲解_第3张图片 整个执行过程图

 

通过把people类聚合到装饰者内,装饰者的方法wear()可以调用people的方法,具体的装饰者Suit类 调用 装饰者的wear(),就会执行Jack的wear()方法,然后相当于递归,返回来在执行Suit类里的方法。不管包几层都一样,层层往里调用。

装饰者模式相当于一层层包装,new的时候被装饰者放在最里面,然后需要添加的职责一层一层给他加上去。

每一个框都是一个整体(People),每次调用附加的职责的时候,都会一层一层往里调,执行完最里面对的在执行外面的,就是super.wear()。

都是继承于同一个抽象类,这样实例化的时候接受者都是这个抽象类,方便操作。

主要的就是装饰者类继承并聚合了People类,这样返回的都是People类,就能和被装饰者类(Jack)一起使用,而且装饰者类的wear()方法,调用了people类(Jack类)的wear类,这个被装饰者的方法,剩下继承装饰者的类都会先调用装饰者的wear(),然后在执行自己要添加的方法,这样就达到了,在不改变原有对象的基础之上,将功能附加到对象上。

 

最后附上两篇文章

装饰者模式与动态代理区别

装饰模式与代理模式的区别(转载)

你可能感兴趣的:(设计模式,JAVA)