④ 设计模式的艺术-10.装饰(Decorator)模式
职责
装饰模式是在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
装饰模式是一种用于代替继承的技术,无需通过继承增加子类就能扩展对象的新功能,使用对象的关联关系代替继承关系,更加灵活,同时避免类型体系的快速膨胀。
1,不改变原类文件。
2,不使用继承。
3,动态扩展。
实现细节

Component抽象构件角色:
真实对象和装饰对象有相同的接口。这样,客户端对象就能够以与真实对象相同的方式同装饰对象交互。
ConcreteComponent 具体构件角色(真实对象):
io流中的FileInputStream、FileOutputStream
Decorator装饰角色:
持有一个抽象构件的引用。装饰对象接受所有客户端的请求,并把这些请求转发给真实的对象。这样,就能在真实对象调用前后增加新的功能。
ConcreteDecorator具体装饰角色:
负责给构件对象增加新的责任。
装饰(Decorator)模式代码示例


代码
package com.cnki.decorator; /**
* 抽象构建
* @author Administrator
*
*/
public interface ICar {
void move();
} //ConcreteComponent 具体构件角色(真实对象)
class Car implements ICar {
@Override
public void move() {
System.out.println("陆地上跑!");
}
} //Decorator装饰角色
class SuperCar implements ICar {
protected ICar car;
public SuperCar(ICar car) {
super();
this.car = car;
} @Override
public void move() {
car.move();
}
} //ConcreteDecorator具体装饰角色
class FlyCar extends SuperCar { public FlyCar(ICar car) {
super(car);
} public void fly(){
System.out.println("天上飞!");
} @Override
public void move() {
super.move();
fly();
} } //ConcreteDecorator具体装饰角色
class WaterCar extends SuperCar { public WaterCar(ICar car) {
super(car);
} public void swim(){
System.out.println("水上游!");
} @Override
public void move() {
super.move();
swim();
} } //ConcreteDecorator具体装饰角色
class AICar extends SuperCar { public AICar(ICar car) {
super(car);
} public void autoMove(){
System.out.println("自动跑!");
} @Override
public void move() {
super.move();
autoMove();
} }
测试
package com.cnki.decorator; import java.io.FileInputStream;
import java.io.InputStreamReader; public class Client {
public static void main(String[] args) {
Car car = new Car();
car.move(); System.out.println("增加新的功能,飞行----------");
FlyCar flycar = new FlyCar(car);
flycar.move(); System.out.println("增加新的功能,水里游---------");
WaterCar waterCar = new WaterCar(car);
waterCar.move(); System.out.println("增加两个新的功能,飞行,水里游-------");
WaterCar waterCar2 = new WaterCar(new FlyCar(car));
waterCar2.move(); // Reader r = new BufferedReader(new InputStreamReader(new FileInputStream(new File("d:/a.txt")))); }
}

开发中使用的场景
IO中输入流和输出流的设计
Swing包中图形界面构件功能
Servlet API 中提供了一个request对象的Decorator设计模式的默认实现类HttpServletRequestWrapper,HttpServletRequestWrapper 类,增强了request对象的功能。
Struts2中,request,response,session对象的处理
IO流实现细节


Component抽象构件角色:
io流中的InputStream、OutputStream、Reader、Writer
ConcreteComponent 具体构件角色:
io流中的FileInputStream、FileOutputStream
Decorator装饰角色:
持有一个抽象构件的引用:io流中的FilterInputStream、FilterOutputStream
ConcreteDecorator具体装饰角色:
负责给构件对象增加新的责任。Io流中的BufferedOutputStream、BufferedInputStream等。
小结
优点
装饰模式(Decorator)也叫包装器模式(Wrapper)
装饰模式降低系统的耦合度,可以动态的增加或删除对象的职责,并使得需要装饰的具体构建类和具体装饰类可以独立变化,以便增加新的具体构建类和具体装饰类。
扩展对象功能,比继承灵活,不会导致类个数急剧增加
可以对一个对象进行多次装饰,创造出不同行为的组合,得到功能更加强大的对象
具体构建类和具体装饰类可以独立变化,用户可以根据需要自己增加新的具体构件子类和具体装饰子类。
总之呢,装饰器模式就是一个可以非常灵活的动态扩展类功能的设计模式,它采用组合的方式取代继承,使得各个功能的扩展更加独立和灵活。
缺点
产生很多小对象。大量小对象占据内存,一定程度上影响性能。
装饰模式易于出错,调试排查比较麻烦。
装饰模式和桥接模式的区别
两个模式都是为了解决过多子类对象问题。但他们诱因不一样。
桥模式是对象自身现有机制沿着多个维度变化,是既有部分不稳定。
装饰模式是为了增加新的功能。
④ 设计模式的艺术-10.装饰(Decorator)模式的更多相关文章
- 设计模式C++描述----10.装饰(Decorator)模式
一. 举例 我之前做过一个文件系统就叫 MyFileSys 吧,后来的话,客户想加入一些附加功能,比如压缩.加密.杀毒之类的操作,这些附加操作没有先后顺序,比如你可以先压缩再加密,也可以先杀毒再压缩, ...
- 《Head First 设计模式》ch.3 装饰(Decorator)模式
设计原则 类应该对修改关闭,对扩展开放(开放-关闭原则).在每个地方使用开放-关闭原则是一种浪费,也没有必要,因为这通常会引入新的抽象层次,增加代码复杂度.需要把注意力集中在设计中最有可能改变的地方. ...
- 设计模式(八)装饰器模式Decorator(结构型)
设计模式(八)装饰器模式Decorator(结构型) 1. 概述 若你从事过面向对象开发,实现给一个类或对象增加行为,使用继承机制,这是所有面向对象语言的一个基本特性.如果已经存在的一个类缺少某些方法 ...
- php设计模式课程---7、装饰器模式如何使用
php设计模式课程---7.装饰器模式如何使用 一.总结 一句话总结: 装饰器的核心是获取了文章类整个类,而不是获取了文章内容,有了这个文章类,我想给你加多少装饰就给你加多少装饰(将文章这个类封装进去 ...
- 大型Java进阶专题(八)设计模式之适配器模式、装饰者模式和观察者模式
前言 今天开始我们专题的第八课了.本章节将介绍:三个设计模式,适配器模式.装饰者模式和观察者模式.通过学习适配器模式,可以优雅的解决代码功能的兼容问题.另外有重构需求的人群一定需要掌握装饰者模式. ...
- 设计模式(九)——装饰者模式(io源码分析)
1 星巴克咖啡订单项目(咖啡馆): 1) 咖啡种类/单品咖啡:Espresso(意大利浓咖啡).ShortBlack.LongBlack(美式咖啡).Decaf(无因咖啡) 2) 调料:Milk.So ...
- 装饰(Decorator)模式
1.装饰(Decorator)模式 动态给一个对象添加一些额外的职责.就增加功能来说,装饰模式比生成子类更为灵活.Component是定义一个对象接口.可以给这些对象动态地添加职责.Concre ...
- 设计模式之第10章-桥接模式(Java实现)
设计模式之第10章-桥接模式(Java实现) “一入软件深似海,从此早睡是路人.黑夜给了我黑色的眼睛,我却用他去寻找八阿哥.”“怎么了,又来那么多的感慨啊.”“还能有什么啊,老板是说让换个APP做,这 ...
- 设计模式的征途—10.装饰(Decorator)模式
虽然目前房价依旧很高,就连我所在的成都郊区(非中心城区)的房价均价都早已破万,但却还是阻挡不了大家对新房的渴望和买房的热情.如果大家买的是清水房,那么无疑还有一项艰巨的任务在等着大家,那就是装修.对新 ...
随机推荐
- 第三章 广义线性模型(GLM)
广义线性模型 前面我们举了回归和分类得到例子.在回归的例子中,$y \mid x;\theta \sim N(u,\sigma ^{2})$,在分类例子中,$y\mid x;\theta \sim ...
- jQuery的2把利器
<!-- $是一个函数,首先是给window添加$,然后该值是一个函数,函数返回的值是对象.1. jQuery核心函数 * 简称: jQuery函数($/jQuery) * jQuery库向外直 ...
- "数学口袋精灵"bug
首先要部署这个app项目就是第一步: 一.前提下载并安装JDK 在线图解:手把手教你安装JDK http://www.lvtao.net/server/windows-setup-jdk.h ...
- PAT L1 - 046 整除光棍
https://pintia.cn/problem-sets/994805046380707840/problems/994805084284633088 这里所谓的“光棍”,并不是指单身汪啦~ 说的 ...
- hdu-题目:1058 Humble Numbes
http://acm.hdu.edu.cn/showproblem.php?pid=1058 Problem Description A number whose only prime factors ...
- postman md5加密 然后传给下一个接口作为参数调用
https://www.v2ex.com/api/nodes/show.json?name=python get请求 断言: tests["Body matches string" ...
- node+express搭建个人网站(2)
node+express搭建个人网站(1)这一节中成功启动了一个网站但还很简陋,仅仅打印了一个helloworld的网页 作为个人网站,我们当然想输出自己设计好的网页, 我们借助 Express 应用 ...
- Contest 9
A:搜索好难啊根本不会啊. B:暴力枚举给哪段前缀乘,维护一些前后缀最大最小值之类的东西就很好算了. #include<iostream> #include<cstdio> # ...
- BZOJ5314 [Jsoi2018]潜入行动 【背包类树形dp】
题目链接 BZOJ5314 题解 设\(f[i][j][0|1][0|1]\)表示\(i\)为根的子树,用了\(j\)个监测器,\(i\)节点是否被控制,\(i\)节点是否放置的方案数 然后转移即可 ...
- Redis的List链表类型命令
List是一个链表结构,主要功能是push.pop.获取一个范围的所有值等等,操作中key理解为链表的名字.list类型其实就是一个每个子元素都是string类型的双向链表.我们可以通过push.po ...