Java设计模式--装饰者模式

在学习Mybatis二级缓存时,了解到sqlsessin对象会使用到一个Executor和相应的CachingExecutor的装饰者模式。所以就来具体了解一下。
Mybatis二级缓存详解–》https://blog.csdn.net/luanlouis/article/details/41408341
强烈推荐!!!
接下来具体讨论装饰者模式:

装饰者模式定义:

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

在程序设计时,我们往往会给一个对象的功能加上一些修饰,对原始的功能进行拓展和增强,以来满足我们的需求。

举个栗子:
有一个唱歌类:

public class Competitor {  

    public void sing()  

    {  

        System.out.println("我唱唱唱......");  

    }  

}  

但是这个是远远不够的,你有一个好嗓门,也是需要包装的,一个裸唱、没有伴奏、没有伴舞的参赛者去比赛哪有什么竞争力啊!于是,我们要对这个参赛者进行包装,在他唱歌的时候加上舞蹈:

public class CompetitorDecorator1 extends Competitor {  
    public void sing()  
    {  
        this.dance();  
        super.sing();  
    }  
    private void dance()  
    {  
        System.out.println("偏偏起舞....");  
    }  
}  

加上舞蹈还不行,还要在唱歌的时候播放合拍的背景音乐:

public class CompetitorDecorator2 extends Competitor {  
    public void sing()  
    {  
        this.playMusic();  
        super.sing();  
    }  
    private void playMusic()  
    {  
        System.out.println("播放背景音乐......");  
    }  
}  

现在的选手都打感情牌,唱完歌后,介绍自己有多不幸,什么没爹啦,没娘啦,早年多不幸啊,自己多努力啊……诸如此类,把评委和观众搞得稀里哗啦的,然后评分就蹭蹭地上去了:

publicclass CompetitorDecorator3 extends Competitor {  
    public void sing()  
    {  
        super.sing();  
        this.introduceBackground();  
    }  
    private void introduceBackground()  
    {  
        System.out.println("悲惨背景介绍,博取同情,赢感情牌....");  
    }  
}  

以上对对象的装饰实现,是通过继承父类的方式,重写父类的方法,加上自己的装饰,强化相应的功能。

现在,我想将播放背景音乐和跳舞这两个装饰都用上,该怎么用呢? 相信很多人都会有这样的一个方法:继承CompetitorDecorator1,重写sing() 方法,将playMusic()方法加进去啊

public class CompetitorDecorator4 extends CompetitorDecorator1 {  
    @Override  
    public void sing()  
    {  
        this.playMusic();  
        super.sing();  
    }  
    private void playMusic()  
    {  
        System.out.println("播放背景音乐......");  
    }  
}  

是的,这样确实可以完成相应的功能。但是有没有觉得怪怪的呢?

  1. 我们在CompetitorDecorator2内已经有了 playMusic() 代码片段,我们在CompetitorDecorator4内有和它完全一样的playMusic()代码片段,这个是不合适的,也是不可取的!

  2. 如果这个选手比较有才,有五花八门的各种装饰,我们为此要增加相应多的装饰类;如果他在这方面有很深的造诣,把这些装饰发挥的淋漓尽致,能把这些装饰融合到一块,这些五花八门的装饰随机组合,这得要衍生多少个子类啊!!!!!

无论怎样,我们不应该采用上面的形式!

如果修饰者修饰过后,可以将这个修饰过的结果传给下一个修饰者,这样的话,就不需要定义这个么多的组合类了,只需要定义相应类型的修饰者就可以了。如果有10 个修饰者的话,只需要定义10 个修饰者的类,然后在实现的时候我们根据需求添加到相应的修饰就可以了。

从上面的的三个装饰来看,无非是在原有 sing() 方法的基础上添加一些辅助的修饰的功能。

在上面的继承机制上,sing方法在装饰者定义的时候已经是一个固定功能的了。如果可以将这个sing()方法变为动态的,即运行时确定的行为,然后再在修饰的时候加上相应的修饰就可以了。

一个类要动态绑定某个对象的行为,是持有相应的对象引用,然后在运行时根据这个引用绑定的具体对象,体现出不同的行为,这个就是动态绑定。

依照上面定义的规则,我们可以通过下面来实现,定义一个Decorator类,持有一个Competitor对象,只有当运行的时候动态绑定到sing() 方法。然后在这个sing() 方法的基础上进行装饰,加入相应的辅助、增强功能。

/**
 * 设计模式:装饰者模式 定义Decorator类, 持有Competitor对象。
 * 在运行时动态绑定sing(),然后在sing()的基础上进行装饰,加入相应的辅助和增强功能。
 * 
 * @Title CompetitorDecorator.java
 * @Package garnisher
 * @Description: TODO
 * @author Young
 * @date 2018年5月21日 下午4:15:59
 * @version V1.0
 */
public class CompetitorDecorator extends Competitor {
    private final Competitor competitor;

    public CompetitorDecorator(Competitor competitor) {
        super();
        this.competitor = competitor;
    }

    @Override
    public void sing() {
        competitor.sing();
    }

}

这样的话,如果我们在创建Decorator对象的时候,如果传入的Competitor 是已经被修饰过的,即sing()方法是被重写过的,那么我们就可以在此基础上再添新的修饰了。

我们重构上面的三个修饰类如下:

/**
 * 设计模式:装饰者模式 在创建装饰者类Decorator后,如果传入的Competitor是已经被修饰过的,
 * 即sing()是被重写过的,我们就可以在此基础上再次添加新功能了。
 * 
 * @Title CompetitorDecoratorA.java
 * @Package garnisher
 * @Description: TODO
 * @author Young
 * @date 2018年5月21日 下午4:20:53
 * @version V1.0
 */
public class CompetitorDecoratorA extends CompetitorDecorator {

    public CompetitorDecoratorA(Competitor competitor) {
        super(competitor);
    }

    @Override
    public void sing() {
        this.dance();
        super.sing();
    }

    private void dance() {
        System.out.println("通过修饰-->舞蹈功能");
    }
}
/**
 * 设计模式:装饰者模式 在创建装饰者类Decorator后,如果传入的Competitor是已经被修饰过的,
 * 即sing()是被重写过的,我们就可以在此基础上再次添加新功能了。
 * 
 * @Title CompetitorDecoratorA.java
 * @Package garnisher
 * @Description: TODO
 * @author Young
 * @date 2018年5月21日 下午4:20:53
 * @version V1.0
 */
public class ComprtitorDecoratorB extends CompetitorDecorator {

    public ComprtitorDecoratorB(Competitor competitor) {
        super(competitor);

    }

    @Override
    public void sing() {
        this.playMusic();
        super.sing();
    }

    private void playMusic() {
        System.out.println("通过修饰-->音乐功能");
    }

}
/**
 * 设计模式:装饰者模式 在创建装饰者类Decorator后,如果传入的Competitor是已经被修饰过的,
 * 即sing()是被重写过的,我们就可以在此基础上再次添加新功能了。
 * 
 * @Title CompetitorDecoratorA.java
 * @Package garnisher
 * @Description: TODO
 * @author Young
 * @date 2018年5月21日 下午4:20:53
 * @version V1.0
 */

public class CompetitorDecoratorC extends CompetitorDecorator {

    public CompetitorDecoratorC(Competitor competitor) {
        super(competitor);

    }

    @Override
    public void sing() {
        this.Backgournd();
        super.sing();
    }

    private void Backgournd() {
        System.out.println("修饰添加-->背景介绍");
    }

}

测试类如下:
我们通过先创建具有固定功能的类。如果要假如具体修饰功能时,再将相应之前的对象作为参数传入,就实现了装饰者模式。

public class Client {
    public static void main(String[] args) {
        Competitor com = new Competitor();

        // 通过父类创建子类对象。同时加入了跳舞修饰功能,传入唱歌的固定功能。
        CompetitorDecorator decorator = new CompetitorDecoratorA(com);
        // 加入背景音乐修饰功能,传入唱歌的固定功能
        decorator = new ComprtitorDecoratorB(decorator);
        // 加上背景修饰功能,传入背景的功能。
        decorator = new CompetitorDecoratorC(decorator);
        decorator.sing();
        System.out.println("装饰完成!!!");
    }
}

通过这种装饰方式,我们可以很方便地根据具体情况增加修饰者,并且不会产生多余的子类,整个过程很灵活,不像单纯使用类继承的方式会产生很多子类。
这里写图片描述
这样给对象动态地添加附加功能。并且装饰者提供了一个灵活的拓展子类功能的备选方案。

具体类结构如下:
这里写图片描述

Component :定义了一个可以被动态添加功能的接口
Decorator :持有一个Component对象的引用,并且定义了一个和Component保持一致的接口。
ConcreteDecorator :为Component添加功能的角色。

优点:
给一个对象动态地、透明地添加职能,即:不影响其他对象。
动态添加的职能能够被取消。

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java设计模式是一组经过实践验证的面向对象设计原则和模式,可以帮助开发人员解决常见的软件设计问题。下面是常见的23种设计模式: 1. 创建型模式(Creational Patterns): - 工厂方法模式(Factory Method Pattern) - 抽象工厂模式(Abstract Factory Pattern) - 单例模式(Singleton Pattern) - 原型模式(Prototype Pattern) - 建造者模式(Builder Pattern) 2. 结构型模式(Structural Patterns): - 适配器模式(Adapter Pattern) - 桥接模式(Bridge Pattern) - 组合模式(Composite Pattern) - 装饰器模式(Decorator Pattern) - 外观模式(Facade Pattern) - 享元模式(Flyweight Pattern) - 代理模式(Proxy Pattern) 3. 行为型模式(Behavioral Patterns): - 责任链模式(Chain of Responsibility Pattern) - 命令模式(Command Pattern) - 解释器模式(Interpreter Pattern) - 迭代器模式(Iterator Pattern) - 中介者模式(Mediator Pattern) - 备忘录模式(Memento Pattern) - 观察者模式(Observer Pattern) - 状态模式(State Pattern) - 策略模式(Strategy Pattern) - 模板方法模式(Template Method Pattern) - 访问者模式(Visitor Pattern) 4. 并发型模式(Concurrency Patterns): - 保护性暂停模式(Guarded Suspension Pattern) - 生产者-消费者模式(Producer-Consumer Pattern) - 读写锁模式(Read-Write Lock Pattern) - 信号量模式(Semaphore Pattern) - 线程池模式(Thread Pool Pattern) 这些设计模式可以根据问题的特点和需求来选择使用,它们提供了一些可复用的解决方案,有助于开发高质量、可维护且易于扩展的软件系统。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值