设计模式笔记-装饰者模式
来源:互联网 发布:看报纸的软件 编辑:程序博客网 时间:2024/04/28 20:39
装饰者模式
继承,是面向对象三大基本特性之一。使用继承能够很容易修改和扩展已有的实现,同时很大程度上能够提升代码的可复用性;事实上在面向对象的设计中,通常也是通过继承来实现对给定类的功能扩展。
但是继承是静态的,在编译时便已经决定了子类的行为,往往不便于我们控制扩展的时机和方式,缺少灵活性,同时破坏了类的封装、不易于后期维护。
这个时候,组合的出现便具有了较大的意义。组合即将一个对象嵌入到另一个对象中,由另一个对象来决定什么时机、是否引用该对象来扩展自己的行为。
不同于继承,使用组合并不会破坏类的封装,而且具有较好的松耦合性、利于系统的维护。当然,最重要的是使用组合能够更为灵活的动态控制对原有类的扩展。
装饰者模式就拥有这样一个非常巧妙的结构,它可以动态添加对象功能。如果要扩展功能,装饰者模式提供了更具有弹性的解决方案。
装饰者模式基本结构:
装饰者模式的关键在于装饰者类和真实对象具有相同的接口,并且装饰者类包含一个真实对象的引用,装饰者类将接收到的请求转交给真实对象,并在转交前后添加自己的行为实现。
我们举个例子:
在咖啡店喝咖啡的时候有的人喜欢加牛奶,也有的人喜欢加冰块。
继承就相当于咖啡店一开始就生产出含有牛奶和冰块的咖啡,这固然是可以的。但是有的人喜欢喝纯咖啡,有的人不喜欢喝加了冰块的咖啡,也有的人喜欢喝更甜的咖啡;市场的需求是复杂的,在这种情况下,往往会丢失一大批的客户。
所以咖啡店并不会一开始就生产出含有牛奶和冰块的咖啡,而是在生产出咖啡后同时提供冰块、牛奶,让客户在需要的时候自行添加。
所谓设计模式,最大的功能或者说目的就在于更好的应对变化。
我们再来看下简单的代码实现:
1、首先自然是公用接口
package cn.service;public interface Compontent { public void operation();}
2、喝咖啡方法,也就是我们的真实对象
package cn.service.impl;import cn.service.Compontent;public class Coffee implements Compontent{ @Override public void operation() { System.out.println("喝咖啡"); }}
3、因为我们要扩展的功能不止一个(除了加冰还可以加牛奶),所以这里我们使用抽象基类方便共用,实现与真实对象相同的接口
package cn.service.impl;import cn.service.Compontent;public abstract class CompontentImpl implements Compontent { Compontent compontent; public CompontentImpl( Compontent c) { compontent = c; }}
4、现在到我们的加冰和加牛奶的功能了,因为父类已经实现了接口,所以这里直接继承便可以了
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(); }}
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类族的实现。
(注:部分图片源于网络)
- 【js设计模式笔记---装饰者模式】
- 设计模式笔记-装饰者模式
- 【js设计模式笔记---装饰者模式】
- 设计模式笔记-装饰者模式
- 设计模式-装饰者模式学习笔记
- 设计模式之装饰者模式-笔记
- 设计模式笔记--装饰模式
- 设计模式笔记:装饰模式
- 8.装饰设计模式(设计模式笔记)
- 设计模式-装饰者模式
- 设计模式:装饰者模式
- 设计模式:装饰者模式
- 设计模式: 装饰者模式
- 设计模式--装饰者模式
- 设计模式-装饰者模式
- 设计模式--装饰者模式
- 设计模式-装饰者模式
- 设计模式------------装饰者模式
- 全栈工程师学习Linux技术的忠告
- 元素,单行文字或多行文字,图片 之 水平垂直居中的方法大全及例子分析
- xcode8的一些变动
- 自定义listview中android:descendantFocusability的属性作用
- iOS动画效果和实现
- 设计模式笔记-装饰者模式
- 跳转界面加载 进度条
- 2039 骑马修栅栏 USACO[图论—欧拉路]
- ssh中Connection is read-only问题的产生原因与解决方法
- 异常处理机制
- 平时在工作或上网时看到的好书
- swift AppDelegate中的方法
- nginx第3方模块编译 及nginx 与php 一致性对memcahce哈希应用
- Linux中wc命令介绍