装饰者模式
来源:互联网 发布:儿童羽绒服推荐知乎 编辑:程序博客网 时间:2024/06/16 21:17
装饰者模式(Decorator Pattern)属于结构型模式,作为现有类的一个包装,能够在不必改变原类文件的情况下动态地扩展功能
继承,是面向对象三大基本特性之一。使用继承能够很容易修改和扩展已有的实现,同时很大程度上能够提升代码的可复用性;事实上在面向对象的设计中,通常也是通过继承来实现对给定类的功能扩展。
但是继承是静态的,在编译时便已经决定了子类的行为,往往不便于我们控制扩展的时机和方式,缺少灵活性,同时破坏了类的封装、不易于后期维护。
这个时候,组合的出现便具有了较大的意义。组合即将一个对象嵌入到另一个对象中,由另一个对象来决定什么时机、是否引用该对象来扩展自己的行为。
不同于继承,使用组合并不会破坏类的封装,而且具有较好的松耦合性、利于系统的维护。当然,最重要的是使用组合能够更为灵活的动态控制对原有类的扩展。
装饰者模式就拥有这样一个非常巧妙的结构,它可以动态添加对象功能。如果要扩展功能,装饰者模式提供了更具有弹性的解决方案。
优势
1、在动态扩展实现类的上可以提供比继承更多的灵活性
2、具体装饰类以及这些装饰类的排列组合,可以得到很多不同行为的组合
3、装饰类和被装饰类可以独立发展,不会相互耦合
不足
1、多层装饰较为复杂
实现
装饰者模式基本结构:
装饰者模式的关键在于装饰者类和真实对象具有相同的接口,并且装饰者类包含一个真实对象的引用,装饰者类将接收到的请求转交给真实对象,并在转交前后添加自己的行为实现。
我们举个例子:
在咖啡店喝咖啡的时候有的人喜欢加牛奶,也有的人喜欢加冰块。
继承就相当于咖啡店一开始就生产出含有牛奶和冰块的咖啡,这固然是可以的。但是有的人喜欢喝纯咖啡,有的人不喜欢喝加了冰块的咖啡,也有的人喜欢喝更甜的咖啡;市场的需求是复杂的,在这种情况下,往往会丢失一大批的客户。
所以咖啡店并不会一开始就生产出含有牛奶和冰块的咖啡,而是在生产出咖啡后同时提供冰块、牛奶,让客户在需要的时候自行添加。
所谓设计模式,最大的功能或者说目的就在于更好的应对变化。
1、首先自然是公用接口
Compontent .java
package cn.service;public interface Compontent { public void operation();}
2、喝咖啡方法,也就是我们的真实对象
Coffee .java
package cn.service.impl;import cn.service.Compontent;public class Coffee implements Compontent{ @Override public void operation() { System.out.println("喝咖啡"); }}
3、因为我们要扩展的功能不止一个(除了加冰还可以加牛奶),所以这里我们使用抽象基类方便共用,实现与真实对象相同的接口
CompontentImpl .java
package cn.service.impl;import cn.service.Compontent;public abstract class CompontentImpl implements Compontent { Compontent compontent; public CompontentImpl( Compontent c) { compontent = c; }}
4、现在到我们的加冰和加牛奶的功能了,因为父类已经实现了接口,所以这里直接继承便可以了
Ice.java
package cn.service.impl;import cn.service.Compontent;public class Ice extends CompontentImpl { public Ice( Compontent c) { super(c); } @Override public void operation() { System.out.println("+冰块"); compontent.operation(); }}
Milk .java
package cn.service.impl;import cn.service.Compontent;public class Milk extends CompontentImpl{ public Milk(Compontent c) { super(c); } @Override public void operation() { System.out.println("+牛奶"); compontent.operation(); }}
5、最后我们便可以灵活的添加自己所喜欢的组合了,可以是先加冰再加牛奶,也可以是先加牛奶再加冰,甚至是可以加了牛奶再加牛奶
public static void main( String[] args){ Compontent compontent = new Milk( new Ice( new Coffee())); compontent.operation(); System.out.println("=========================="); compontent = new Ice( new Milk( new Coffee())); compontent.operation(); System.out.println("=========================="); compontent = new Milk( new Milk( new Coffee())); compontent.operation(); }
这个时候大家会发现,对原有对象的扩展变得很灵活了,但是同时也产生了很多小对象。更灵活的特性也就意味着系统的复杂性更高,也同时意味着比继承更容易出错,出错后的排查也更为繁琐。
所以在我们使用装饰者模式的时候需要把握一个度,过度的使用并不可取。
装饰者模式可以让使用者针对接口编程,之后通过不同的方式实现接口类而达到实现不同功能的目标。这种使用模式是否有些似曾相识的感觉?
在Java中,装饰者模式有个很典型的应用:InputStream和OutputStream类族的实现。
- 装饰者模式(Derector)
- 装饰者模式
- Decorator 装饰者模式
- 装饰者设计模式
- 装饰者模式
- 装饰者模式
- 装饰者模式
- 装饰者模式(Decorator)
- 装饰者模式
- 装饰者模式
- 装饰者模式
- 装饰者模式 DecoratorPattern
- 设计模式 - 装饰者
- 装饰者模式
- 装饰者模式
- 装饰者模式 - 2
- 装饰者模式
- 装饰者模式
- Java开发环境的配置步骤
- A Circle and a Square----计算几何,判断点是否在图形内
- Opencv研读笔记:haartraining程序之莫名其妙的条件宏ICV_DEF_FIND_STUMP_THRESHOLD_SQ解释~
- EasyIPCamera Android结合EasyPlayer播放器实现教室、会议、展销同屏直播
- java多态
- 装饰者模式
- android 对话框
- 通过oledb驱动读取excel、csv数据丢失解决方案
- 链表写的通讯录
- 深入理解JVM-虚拟机加载机制-类加载过程
- 安卓程序开发作业(一、2017/2/23)
- [转载]EasyPlayer实现视频的局部缩放、平移功能(类似快手视频)
- 知识库--Concurrency Using STM(122)
- 细说mysql索引