对于装饰器模式,其主要是为了:在不改变本体特征的情况下,对其进行包装、装饰,目的是为了补充、扩展、增强其功能。

有三个原则:

  1. 不能改变本体的特征
  2. 要对本体的功能进行扩展
  3. 装饰器脱离了本体则没有任何含义

下面是一个具体的例子:

对于一个水果类

public class Fruit {
//代表水果的名字:苹果,西瓜,桃子,橘子等等。。。
public String name; public Fruit(String name){
this.name = name;
} public String getName(){
return this.name;
} public void eat(){
System.out.println(getName() + "被吃了");
}
}

每一个水果都有一个“被吃”的方法

public static void main(String[] args) {

        Fruit apple = new Fruit("苹果");
Fruit watermelon = new Fruit("西瓜");
Fruit orange = new Fruit("橘子");
Fruit peach = new Fruit("桃子"); apple.eat();
watermelon.eat();
orange.eat();
peach.eat(); }

输出

苹果被吃了

西瓜被吃了

橘子被吃了

桃子被吃了


但现在我想对水果类添加一个功能--“被洗”

于是可以想到在Fruit类中添加一个功能wash()即可,并且在eat()方法中调用即可;

    public void wash(){
System.out.println(getName() + "被洗了");
}
public void eat(){
wash();
System.out.println(getName() + "被吃了");
}

但是实际上对于Fruit的一些其他水果是并不需要wash()这个方法的,例如橘子,西瓜等,他们是不需要执行wash()这个操作;所以这样子直接加在Fruit类上显然是不合适的

那么可能就会想到继承,只需要对要洗的水果创建一个类,并继承Fruit类,重写eat()方法即可;

例如:

public class Apple extends Fruit {

    public Apple(String name){
super(name);
} public void wash(){
System.out.println(getName()+"被洗了");
} @Override
public void eat() {
wash();
super.eat();
}
}

测试:

public static void main(String[] args) {

        //注意此处new 的是Apple对象,利用多态性质
Fruit apple = new Apple("苹果");
Fruit watermelon = new Fruit("西瓜");
Fruit orange = new Fruit("橘子");
Fruit peach = new Fruit("桃子"); //调用Apple类的eat方法
apple.eat();
watermelon.eat();
orange.eat();
peach.eat();
}

苹果被洗了

苹果被吃了

西瓜被吃了

橘子被吃了

桃子被吃了

我们可以看到苹果是被洗了的,但是对于桃子来说,桃子也需要被洗,那么就又需要写一个Peach类,那还有诸多需要洗的水果,也不能每一个都创建一个类然后重写eat()方法

于是我们就可以使用到装饰器模式,我们可以对需要洗的水果进行包装

装饰器(洗)中保存一个被装饰的对象(水果),之后对需要装饰的方法(吃)进行重写,并且进行装饰(被洗),之后再通过被装饰的对象(水果),去调用它本身的方法(吃)

public class WashDecorator {

    Fruit fruit;

    public WashDecorator(Fruit fruit){
this.fruit = fruit;
} public void eat(){
//
if(fruit != null){
System.out.println(fruit.getName() + "被洗干净了");
fruit.eat();
}
}
}

这样子我们就可以对需要洗的水果进行包装

public static void main(String[] args) {

        Fruit apple = new Fruit("苹果");
//使用装饰器对苹果进行包装
WashDecorator appleWash = new WashDecorator(apple); Fruit watermelon = new Fruit("西瓜");
Fruit orange = new Fruit("橘子"); Fruit peach = new Fruit("桃子");
//使用装饰器对桃子进行包装
WashDecorator peachWash = new WashDecorator(peach); //使用装饰器调用eat方法
appleWash.eat();
watermelon.eat();
orange.eat();
peachWash.eat();
}

结果

苹果被洗干净了
苹果被吃了
西瓜被吃了
橘子被吃了
桃子被洗干净了
桃子被吃了

当然我们上面的案例可能不是很实际,下面是一个实际的例子,也是很经典的装饰器模式的案例

  • 也就是我们的FileInputStream与BufferedInputStream

  • 实际上BufferedInputStream就相当于FileInputStream的一种装饰器

我们在使用时常常使用BufferedInputStream去包装FileInputStream,之后去调用bis的read方法

        FileInputStream fis = new FileInputStream(path);
BufferedInputStream bis = new BufferedInputStream(fis);

对于FileInputStream 来说,我们要添加一个缓存区功能,我们能在FileInputStream 本类来加吗?

不能,因为不是所有的FileInputStream 都需要一个缓存区,那么就使用到了装饰器模式,在不能改变本体的特征的情况下要对本体的功能进行扩展

使用一个BufferedInputStream 类来装饰FileInputStream 类,BufferedInputStream 里面实现了缓存的功能,当我们的业务逻辑需要用到缓存功能的时候,我们就可以对其进行包装

关于FileInputStream 与BufferedInputStream 详情见下一篇文章:IO流-字节流BufferedInputStream 底层实现

Decorator装饰器模式个人理解的更多相关文章

  1. 12、Decorator 装饰器 模式 装饰起来美美哒 结构型设计模式

    1.Decorator模式 装饰模式又名包装(Wrapper)模式.装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 装饰器模式(Decorator Pattern)允许向一个现 ...

  2. Decorator(装饰器模式)

    装饰器模式允许我们根据运行时不同的情景动态地为某个对象调用前后添加不同的行为动作. <?php class HtmlTemplate { // any parent class methods ...

  3. 十二、Decorator 装饰器模式

    设计: 代码清单: Display public abstract class Display { public abstract int getColumns(); public abstract ...

  4. java设计模式之七装饰器模式(Decorator)

    顾名思义,装饰模式就是给一个对象增加一些新的功能,而且是动态的,要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例,关系图如下: Source类是被装饰类,Decorator类是一个 ...

  5. Java设计模式12:装饰器模式

    装饰器模式 装饰器模式又称为包装(Wrapper)模式.装饰器模式以多客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 装饰器模式的结构 通常给对象添加功能,要么直接修改对象添加相应的功能, ...

  6. java进阶系列之装饰器模式

    1.介绍 装饰器模式顾名思义就是装饰某个对象的,是一种结构型模式.装饰器模式允许向一个现有对象添加新的功能,同时不改变其结构,用户可以随意的扩展原有的对象.它是作为现有的类的一个包装.装饰器模式一方面 ...

  7. 装饰器模式(Decorator)——深入理解与实战应用

    本文为原创博文,转载请注明出处,侵权必究! 1.初识装饰器模式 装饰器模式,顾名思义,就是对已经存在的某些类进行装饰,以此来扩展一些功能.其结构图如下: Component为统一接口,也是装饰类和被装 ...

  8. 设计模式(八)装饰器模式Decorator(结构型)

    设计模式(八)装饰器模式Decorator(结构型) 1. 概述 若你从事过面向对象开发,实现给一个类或对象增加行为,使用继承机制,这是所有面向对象语言的一个基本特性.如果已经存在的一个类缺少某些方法 ...

  9. 装饰器模式 Decorator 结构型 设计模式 (十)

    引子           现实世界的装饰器模式 大家应该都吃过手抓饼,本文装饰器模式以手抓饼为模型展开简介 "老板,来一个手抓饼,  加个培根,  加个鸡蛋,多少钱?" 这句话会不 ...

随机推荐

  1. jQuery中ajax请求的六种方法(三、六):load()方法

    6.load()方法 load的html页面 <!DOCTYPE html> <html> <head> <meta charset="UTF-8& ...

  2. 微信小程序学习笔记五 常见组件

    1. 常见组件 重点讲解小程序中常用的布局组件 1.1 view 代替 原来的div标签 <!-- pages/index/index.wxml --> <view hover-cl ...

  3. 翻译Go Blog: 常量

    常量 Pob Pike 2014年8月24日 原文 介绍 Go是一门静态语言,它不允许不同数字类型间的操作.你不能将一个浮点数(float64)和一个整数(int)相加,也不能将一个32位整数(int ...

  4. UVA1620 Lazy Susan(结论证明)

    结论: 当 \(n\geq 6\) 时,若 \(n\) 是奇数且输入序列的逆序对数是奇数,则无解,否则有解. 当 \(n=4\) 或 \(n=5\) 时,答案个数及其有限,只有这个环是 \(1\) 到 ...

  5. Vivado实战—单周期CPU指令分析

    引言   不知道你是否和我有过同样的感受,<计算机组成原理>这门学科学起来如此的艰难:一节课下来,教室黑板上留下了满满的 "足迹",看上去也挺简单的,不就是 0 和 1 ...

  6. 登录用户出现‘’-bash-4.2$‘’的问题解决

    Linux系统切换用户时如显示的是-bash-4.2# 而不是user@主机名 + 路径的显示方式,以往一直用的脚本也不能执行起来: 原因是在用useradd添加普通用户时,有时会丢失家目录下的环境变 ...

  7. 文件权限的管理以及acl权限列表

    ls -l? 文件名称 上面的命令以长格式显示文件与目录,每一行都是一个文件或目录的属性数据,每个文件或子目录的属性数据又以7个字段显示,各个字段的说明如下: (1)文件类型与权限:该字段共有10个字 ...

  8. 洛谷P1083 借教室 题解

    题目 [NOIP2012 提高组] 借教室 题解 这道题是几周之前做到的一道题,本来不想讲的,因为这道题也是用到了二分答案的方法,这类题目之前已经发布过两篇题解了.但这道题还运用了差分数组这个思想,所 ...

  9. Hexo+Butterfly主题美化

    前言 本博客基于Hexo框架搭建,用到 hexo-theme-butterfly 主题(本人博客Butterfly版本3.4.0),hexo-theme-butterfly是基于Molunerfinn ...

  10. Golang入门学习(二):控制分支

    文章目录 @[TOC] 1. 控制分支 1.1 if-else分支 1.2 switch分支 1.4 while 和do...while循环结构 1.5 多种循环结构 1.6 break 1.7 co ...