JAVA设计模式 之 装饰器模式

倾然丶 夕夏残阳落幕 提交于 2019-12-17 20:24:51

装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。

当我们想要扩展一个类,又由于继承类过多,工作量大,耦合度过高等原因纠结的时候,装饰器模式无疑是最好的选择。这种模式做到了装饰类和被装饰类相互独立发展,装饰类可以动态的添加功能,相比于维护庞大的功能不同的被装饰类类来说更灵活。这里举个简单的例子:

一个表演家Actor抽象类,具有表演的能力。

public abstract class Actor {

    /**
     * 表演
     */
    public abstract void act();
}

三个子类,舞蹈家DanceActor,演员MovieActor,歌唱家SingActor继承了表演家Actor:

public class DanceActor extends Actor {

    @Override
    public void act() {
        System.out.println("跳舞");
    }
}

public class MovieActor extends Actor {

    @Override
    public void act() {
        System.out.println("演电影");
    }
}

public class SingActor extends Actor {

    @Override
    public void act() {
        System.out.println("唱歌");
    }
}

现在我们要让演员和歌唱家具有发声的功能,如果不适用装饰者模式,我们需要在这两个字类中实现这个功能,由于是两个子类,这样实现看起来没有问题,但是如果大量的子类需要具有相同的功能,这种方法就比较难以接受。接下来我们使用装饰器模式来实现。首先定义一个装饰类基类:

public class FilterActorDetorator extends Actor{

    protected volatile Actor actor;

    public FilterActorDetorator(Actor actor) {
        this.actor = actor;
    }

    @Override
    public void act() {
        actor.act();
    }
}

这个基类维护了Actor的变量,并实现了Actor相同的方法,这样子类装饰器在使用时并不会感受到什么差异。接下来我们构建一个子装饰类:

public class VoiceActorDetorator extends FilterActorDetorator {

    public VoiceActorDetorator(Actor actor) {
        super(actor);
    }

    public void getVoice(){
       if(actor instanceof SingActor || actor instanceof MovieActor){
           System.out.println("发声");
       }else{
           throw new RuntimeException("不具备该功能");
       }
    }
}

子装饰类VoiceActorDetorator添加了发声的功能,但是需要注意的是:并不是所有的子类都具备该功能,所以在使用时需要注意,这也是装饰器模式的弊端:

public class DecoratorMain {
    public static void main(String[] args) {
        SingActor singActor = new SingActor();
        DanceActor danceActor = new DanceActor();
        VoiceActorDetorator voiceActorDetorator = new VoiceActorDetorator(singActor);
        VoiceActorDetorator voiceActorDetorator1 = new VoiceActorDetorator(danceActor);
        voiceActorDetorator.act();
        voiceActorDetorator1.act();
        voiceActorDetorator.getVoice();
        voiceActorDetorator1.getVoice();
    }
}


控制台:
Exception in thread "main" java.lang.RuntimeException: 不具备该功能
	at com.designmodel.decorator.VoiceActorDetorator.getVoice(VoiceActorDetorator.java:21)
	at com.designmodel.decorator.DecoratorMain.main(DecoratorMain.java:20)
唱歌
跳舞
发声

装饰器模式的优缺点都很明显,优点是灵活,解耦;缺点是复杂。下图是这个装饰器模式的结构:

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!