常用设计模式:装饰者模式

Wellhold Wellhold     2022-09-20     217

关键词:

  今天看了一篇很棒的介绍装饰者模式的文章,于是就按照以往的惯例,学习了之后手动的码了这么一篇随记记录自己的体会,并且参考原文的例子,自己手动的实现了一遍整个demo,原文地址为:http://blog.csdn.net/zhaoyanjun6/article/details/56488020

  首先我们来大体了解一下装饰者模式究竟是个什么东西呢?所谓的装饰者,可以参考现在很火的一个游戏——绝地大逃杀里头的枪械自由改装的概念来解释装饰者模式的概念。现在有这么一把AK47枪,除了枪之外,没有任何以外的配件,看到人就只能拿着把裸的AK随便的突突突,碰运气看看能不能打中人。而突然该玩家获得了一个八倍瞄准镜,和一个消声器,这时候该玩家就可以把这个瞄准镜和消声器安装到AK上,然后他就可以用这把AK的八倍镜去瞄准2000米外的敌人,然后用AK上的消声器,悄无声息的击杀别人。而这时候,这个玩家用腻了AK,于是又把这个瞄准镜和消声器安装到了自己的沙漠飞鹰的手枪上,这时候,这个沙漠飞鹰就具有了和AK的一样的功能。这个就是我们所谓的装饰者模式,通过装饰器装饰之后,我们的目标就会具有一个新的功能。

  那么了解了装饰者模式是什么之后,它的好处就更一目了然了吧?在拓展一个类的功能的时候,通常可以使用继承来实现功能的拓展,如果这些需要拓展的功能的种类很繁多,那么势必生成很多子类,增加系统的复杂性,同时,使用继承实现功能拓展,我们必须可预见这些拓展功能,这些功能是编译时就确定了,是静态的。而通过装饰者模式来做这个事情,就可以完美的解决这些问题。就用我们刚刚那个例子来说,如果通过继承来实现的话,那么势必AK47下会有这么些子类,带瞄准镜的AK,带消声器的AK,带瞄准镜和消声器的AK,这就很蛋疼咯吧?而且如果要用在沙漠飞鹰之上,又要有带瞄准镜的沙漠飞鹰子类等,会有无数的子类出现。

  二话不说 ,那么接下来我们先来看看代码

先看看被装饰者的代码:

public interface Gun {

    void status();
    
}

public class AK47 implements Gun {

    @Override
    public void status() 
    {
        System.out.println("当前AK没有任何配件");
        
    }
}

public class DesertEagle implements Gun {

    @Override
    public void status() 
    {
        System.out.println("当前沙漠飞鹰没有任何配件");
        
    }
}

被装饰者都共同实现了一个叫GUN的接口(AK和沙漠飞鹰都属于枪,在这个接口下有一个方法叫status表示当前该枪具有什么配件),接下来看看我们的装饰器类:

public abstract class GunPart implements Gun {

    Gun gun;
    
    public GunPart(Gun gun) 
    {
        this.gun=gun;
    }
    
    @Override
    public void status() {
        gun.status();
    }
}


public class muffler extends GunPart {

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

    @Override
    public void status() {
        super.status();
        say();
    }

    public void say()
    {
        System.out.println("该枪有了消声器");
    }
}

public class telescope extends GunPart {

    
    public telescope(Gun gun) {
        super(gun);
        // TODO Auto-generated constructor stub
    }

    @Override
    public void status() {
        // TODO Auto-generated method stub
        super.status();
        say();
    }
    
    public void say()
    {
        System.out.println("该枪有了瞄准镜");
    }

}

在装饰器当中,我们抽象了这么一个抽象类叫做GunPart,而不论是消声器还是瞄准镜都是属于GunPart(枪械配件的一部分)所以都是继承了这个GunPart,而这个GunPart同时也实现了Gun这个接口,注意这里是重点,这个GunPart一定也要实现这个Gun接口,否则就无法实现装饰器可叠加的效果了。而继承了GunPart的子类,都会重写父类的status方法,重写的内容第一行一定是调用父类的.status方法。然后再加上该子类添加的特色功能,在例子中是say()方法。

接下来看看我们的测试代码和测试结果:

public class test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Gun AK47=new AK47();
        muffler muffler=new muffler(AK47);
        telescope telescope=new telescope(muffler);
        telescope.status();
        
        System.out.println();
        
        Gun DS=new DesertEagle();
        muffler muffler1=new muffler(DS);
        telescope telescope1=new telescope(muffler1);
        telescope1.status();
    }

}
当前AK没有任何配件
该枪有了消声器
该枪有了瞄准镜

当前沙漠飞鹰没有任何配件
该枪有了消声器
该枪有了瞄准镜

这样,我们一个完整的装饰者模式的demo就写完了,那么我们来试着总结一下装饰者模式的一些重点,首先看看这个继承和实现关系图:

  • Component抽象构件角色:真实对象和装饰对象有相同的接口。这样,客户端对象就能够以与真实对象相同的方式同装饰对象交互。用我们例子里的话,就是Gun这个接口。
  • ConcreteCompoent 具体构建角色(真实对象):定义一个将要接收附加责任的类。用我们例子里的话,就是AK47这个类和沙漠飞鹰这个类。
  • Decorator装饰角色:持有一个抽象构件的引用。装饰对象接受所有客户端的请求,并把这些请求转发给真实的对象。这样,就能在真实对象调用前后增加新的功能。例子里对应的是GunPart这个抽象类。
  • ConcreteDecorate具体装饰角色:负责给构件对象增加新的功能。对应的就是消声器和八倍镜那个类了。

总的来说,装饰模式降低系统的耦合度,可以动态的增加或删除对象的责任(在写test类的方法的时候,动态的添加或者不添加),并使得需要装饰的具体构建类和具体装饰类可以独立变化,以便增加新的具体构建类和具体装饰类。

优点

  •  扩展对象功能,比继承灵活,不会导致类个数急剧增加。
  • 可以对一个对象进行多次装饰,创造出不同行为的组合,得到功能更加强大的对象。
  • 具体构 件 类和具体装饰类可以独立变化,用户可以根据需要自己增加新的 具体构件子类和具体装饰子类。

缺点

  • 产生很多小对象。大量小的对象占据内存,一定程度上影响性能。
  • 装饰模式易出错,调试排查比较麻烦。

那么装饰者模式讲到这里,就差不多。。。。。。。。。。。。。。。壳斗麻袋~!!!!你看到这里肯定会突然发觉,诶?这个装饰者模式怎么特么的和静态代理那么像啊

1.同样都是增强类(装饰器)和目标类(被装饰者)实现了同一个接口。

2.同样都是通过增强类(装饰器)重写和目标类(被装饰者)来增强方法。

 

这特么不是一样的嘛?

其实我看到这里的时候,也产生了这么一个疑问,于是就去查阅了其他关于代理模式和装饰者模式,于是得到了以下三点:

1.装饰器模式关注于在一个对象上动态的添加方法,然而代理模式关注于控制对对象的访问。

2.装饰器模式可以叠加的为被装饰者装饰,而代理不支持多层嵌套。这也是我为什么在前边“划重点”的原因。

好啦,具体的还是自己体会吧。(其实自己这一块也还不大会,一起学习咯)

设计模式--装饰者模式

 装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更加有弹性的替代方案。对于我自己的理解:装饰者模式就是一个在继承层面上的递归。对于装饰者模式而言,有两个很重要的概念:component与&nb... 查看详情

设计模式---装饰者模式(代码片段)

...饰模式的优点装饰模式的缺点装饰模式注意事项适用场景设计模式在JAVAI/O库中的应用透明和半透明的装饰模式的区别参考文章介绍装饰者模式(DecoratorPattern):动态地给一个对象增加一些额外的职责࿰ 查看详情

设计模式-装饰者模式

装饰者模式(Decorator)装饰者模式(Decorator):动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。 装饰者模式结构:   抽象构件(Component)角色:给出一个抽象接口,以规范准... 查看详情

设计模式——装饰者模式

装饰者模式:动态地将责任附加到对象上。若要拓展功能,装饰者提供了比继承更有弹性的替代方案。一般装饰者包括组件和装饰者对象,组件基类包含所需要装饰的部分,具体组件和装饰类都继承与组件基类。这样做的保证是... 查看详情

设计模式学习_装饰者模式(代码片段)

装饰者模式概述装饰者模式动态地将责任附加到对象身上.若要扩展功能,装饰者提供了比继承更富有弹性的替代方案.装饰者和被装饰者拥有相同的超类可以使用一个或多个装饰者包装一个对象装饰者可以在所委托被装饰者的行为... 查看详情

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

1、简介  装饰者模式又叫包装模式(wrapper),装饰者模式以对客户端透明的方式扩展对象的功能,是继承关系的一种替代方案。  装饰者与被装饰者拥有共同的超类,继承的目的是继承类型,而不是行为。 2、装饰者模... 查看详情

设计模式——装饰者模式(代码片段)

目录问题描述版本(一)版本(二)——装饰者模式 1.版本(一)存在的缺点2.装饰者模式3.装饰者模式实现咖啡订单系统装饰者模式的应用——javaI/O 一个非常好的例子——编写自己的javaI/O装饰者问题描... 查看详情

设计模式之装饰者设计模式(代码片段)

设计模式之装饰者设计模式1.定义:动态的将责任附加到对象上。想要扩展功能,装饰者是有别于继承的另外一种选择。就增加功能而言,装饰者模式比子类更加的灵活涉及到的设计原则:类应该对扩展开放,对修改关闭要点:1.... 查看详情

设计者模式装饰者模式

此设计模式遵循的设计原则之一:类应该支持扩展,而拒绝修改(Open-ClosedPrinciple)装饰者模式简述装饰者模式通过组合的方式扩展对象的特性,这种方式允许我们在任何时候对对象的功能进行扩展甚至是运行时扩展,而若我们... 查看详情

装饰者模式

装饰者模式以对客户透明的方式动态地给一个对象附加上更多的责任,装饰者模式相比生成子类可以更灵活地增加功能。优点:装饰这模式和继承的目的都是扩展对象的功能,但装饰者模式比继承更灵活通过使用不同的具体装饰... 查看详情

戏说模式之装饰者模式(游戏)

装饰者模式定义装饰者(Decorator)模式提供了一种方法,使得在不改变原有类的基础上可以动态的扩展一个对象的功能。即动态的将指着附加到对象上。装饰者模式的特点1、装饰对象和被装饰对象实现了相同的接口。客户端可以不... 查看详情

java设计模式之装饰者模式

装饰者模式出现的原因要对类的功能进行增强,可以新建一个类继承这个类,这种方法可以解决问题,但如果增加的功能越来越多,那继承的层次就越来越深,造成继承冗余的问题装饰者模式可以不用继承类而增强类的功能,原... 查看详情

装饰者模式(代码片段)

  最近学习设计模式,跟着《大话设计模式》和《HeadFirst设计模式》两本书边练边学,学到装饰者模式的时候,死活理解不了装饰者模式是怎么调用的,最后搜索了很多资料,才搞明白装饰者模式是怎么层层调用的。下面先贴... 查看详情

装饰者模式

装饰模式介绍装饰模式是结构型设计模式之一,不使用继承和改变类文件的情况下,动态地扩展一个对象的功能,是继承的替代方案之一(就增加功能来说,装饰者模式相比生成子类更为灵活。)。它是通过创建一个包装对象,... 查看详情

设计模式-装饰者模式

定义:装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。对象:   抽象组件:定义一个抽象类或接口,来规范准备附加功能的类;   具体组件:将要被附加功能的类,实... 查看详情

设计模式装饰者模式(代码片段)

我们到咖啡店喝咖啡的时候,往往会根据各自的口味去选择咖啡和各种配料,比如咖啡可以选择综合、深焙、低咖啡因、浓缩,配料可以选搭牛奶、摩卡、豆浆、奶泡。这个情境下就可以使用装饰者模式,用配料对咖啡进行装饰... 查看详情

java设计模式系列之装饰者模式

装饰者模式的定义动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案 装饰者模式的UML类图 查看详情

装饰者模式

...端透明的方式动态地将责任附加到对象上.若要扩展功能,装饰者提供了比继承更有弹性的替代方案。装饰者模式用意是要保持对象接口,增强对象性能.实际生活中经常发现装饰者模式.比如,你需要装裱挂画,你不想讲画和画框定死... 查看详情