Decorator装饰器模式个人理解
对于装饰器模式,其主要是为了:在不改变本体特征的情况下,对其进行包装、装饰,目的是为了补充、扩展、增强其功能。
有三个原则:
- 不能改变本体的特征
- 要对本体的功能进行扩展
- 装饰器脱离了本体则没有任何含义
下面是一个具体的例子:
对于一个水果类
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装饰器模式个人理解的更多相关文章
- 12、Decorator 装饰器 模式 装饰起来美美哒 结构型设计模式
1.Decorator模式 装饰模式又名包装(Wrapper)模式.装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 装饰器模式(Decorator Pattern)允许向一个现 ...
- Decorator(装饰器模式)
装饰器模式允许我们根据运行时不同的情景动态地为某个对象调用前后添加不同的行为动作. <?php class HtmlTemplate { // any parent class methods ...
- 十二、Decorator 装饰器模式
设计: 代码清单: Display public abstract class Display { public abstract int getColumns(); public abstract ...
- java设计模式之七装饰器模式(Decorator)
顾名思义,装饰模式就是给一个对象增加一些新的功能,而且是动态的,要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例,关系图如下: Source类是被装饰类,Decorator类是一个 ...
- Java设计模式12:装饰器模式
装饰器模式 装饰器模式又称为包装(Wrapper)模式.装饰器模式以多客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 装饰器模式的结构 通常给对象添加功能,要么直接修改对象添加相应的功能, ...
- java进阶系列之装饰器模式
1.介绍 装饰器模式顾名思义就是装饰某个对象的,是一种结构型模式.装饰器模式允许向一个现有对象添加新的功能,同时不改变其结构,用户可以随意的扩展原有的对象.它是作为现有的类的一个包装.装饰器模式一方面 ...
- 装饰器模式(Decorator)——深入理解与实战应用
本文为原创博文,转载请注明出处,侵权必究! 1.初识装饰器模式 装饰器模式,顾名思义,就是对已经存在的某些类进行装饰,以此来扩展一些功能.其结构图如下: Component为统一接口,也是装饰类和被装 ...
- 设计模式(八)装饰器模式Decorator(结构型)
设计模式(八)装饰器模式Decorator(结构型) 1. 概述 若你从事过面向对象开发,实现给一个类或对象增加行为,使用继承机制,这是所有面向对象语言的一个基本特性.如果已经存在的一个类缺少某些方法 ...
- 装饰器模式 Decorator 结构型 设计模式 (十)
引子 现实世界的装饰器模式 大家应该都吃过手抓饼,本文装饰器模式以手抓饼为模型展开简介 "老板,来一个手抓饼, 加个培根, 加个鸡蛋,多少钱?" 这句话会不 ...
随机推荐
- C# lock的语法糖原理--《.net core 底层入门》之自旋锁,互斥锁,混合锁,读写锁
在多线程环境中,多个线程可能会同时访问同一个资源,为了避免访问发生冲突,可以根据访问的复杂程度采取不同的措施 原子操作适用于简单的单个操作,无锁算法适用于相对简单的一连串操作,而线程锁适用于复杂的一连 ...
- Docker是简介
Docker是什么 使用最广泛的开源容器引擎 一种操作系统级的虚拟化技术 依赖于Linux内核特性:Namespace(资源隔离)和Cgroups(资源限制) 一个简单的应用程序打包工具 D ...
- BeanUtils实现对象拷贝(三)
package beanutil; import java.lang.reflect.InvocationTargetException; import java.util.Date; import ...
- git所遇到的问题
出现这种情况,或 ERROR: Repository not found. fatal: 无法读取远程仓库. 解决办法如下: 1.先输入$ git remote rm origin(删除关联的orig ...
- 证明:(a,[b,c]) = [(a,b),(a,c)]
这题是潘承洞.潘承彪所著<初等数论>(第三版)第一章第5节里一个例题,书中采用算术基本定理证明,并指出要直接用第4节的方法来证是较困难的. 现采用第4节的方法(即最大公约数理论里的几个常用 ...
- 【Qt pro 文件配置】
一.默认配置 默认的pro文件配置如下: 如果采用Qt默认的pro配置,其编译后产生的文件会默认集中分布在debug和release目录下,如下图的obj和moc等文件对后续打包发布并没有意义. 二. ...
- 致敬mentohust,路由器使用Socket认证华科校园网
致敬mentohust,路由器使用Socket认证华科校园网 前言: 上一篇文章中,为了解决ESP32华科无线网认证的问题,我成功把网页认证机制用Python+Socket复现.但痛点依然存在,无线网 ...
- JDK1.8源码阅读笔记(2) AtomicInteger AtomicLong AtomicBoolean原子类
JDK1.8源码阅读笔记(2) AtomicInteger AtomicLong AtomicBoolean原子类 Unsafe Java中无法直接操作一块内存区域,不能像C++中那样可以自己申请内存 ...
- WEB漏洞——XXE
XXE漏洞又称XML外部实体注入(XML External Entity) 介绍XXE漏洞前先说一下什么是XML XML语言 XML用于标记电子文件使其具有结构性的标记语言,可以用来标记数据定义数据类 ...
- NOIP模拟21:「Median·Game·Park」
T1:Median 线性筛+桶+随机化(??什么鬼?). 首先,题解一句话秀到了我: 考虑输入如此诡异,其实可以看作随机数据 随机数据?? 这就意味着分布均匀.. 又考虑到w< ...