设计模式学习(三)——装饰器模式

前言

距离上一次正儿八经地写随笔已经有一段时间了,虽然2月10号有一篇关于泛型的小记,但是其实只是简单地将自己的学习代码贴上来,为了方便后续使用时查阅,并没有多少文字和理解感悟。之所以在今天觉得有必要写点东西,主要是因为对自己这一周的状态不满意。表面上看,周一到周三都是加班到比较晚,周一回到家快10点了,还看了会书到12点半,但是实际上,我知道,自己的精神状态出现了松懈,心态上有点浮躁,态度的问题是不能容忍的。因此决定在今天写点东西,希望让自己能静下来,重新出发。

一、OOP(Object Oriented Programming)中的装饰器模式

在《HeadFirst设计模式》中,作者给出的定义是:装饰者模式动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

其实从字面上,这个定义并不是那么容易理解。我自己总结了下OOP中的装饰器模式特点:

1. 装饰者与被装饰者会继承相同的父类。

2. 装饰者会有一个私有变量持有被装饰者的引用。

3. 装饰者将自己的属性附加到到被装饰者上。

为了学以致用,我想用生活中的例子来描述装饰者模式的使用姿势。

场景:最近我厂由于业务扩展,有大批职位需要招聘,而各个职位对求职者的要求参差不齐,其中有一部分岗位对人才的要求非常相近但是又不完全相同,这边提取出一些出现频率比较高的要求:计算机专业,熟悉Java,熟悉JVM,测试分析能力,自动化测试能力。

下面就是使用装饰者模式实现的代码:

Job(被装饰者)基类:

public abstract class Job {private String title="unknown";public String getTitle(){return title;};public void setTitle(String title){this.title = title;}public abstract String getJobDescription();
}

JobRequirement(装饰者)基类:

public abstract class JobRequirement extends Job {    //重写getDescription方法public abstract String getJobDescription();
}

SoftwareDeveloper(职位1):

public class SoftwareDeveloper extends Job{public SoftwareDeveloper(){this.setTitle("Software Developer");}@Overridepublic String getJobDescription() {return "familiar with Java";}
}

SoftwareTester(职位2)

public class SoftwareTester extends Job{public SoftwareTester() {this.setTitle("Software Tester");}@Overridepublic String getJobDescription() {return "familiar with test-analysis";}
}

AutotestRequirement(自动化测试要求):

public class AutotestRequirement extends JobRequirement{Job job;public AutotestRequirement(Job job){this.job=job;}@Overridepublic String getTitle() {return job.getTitle();}@Overridepublic String getJobDescription() {return job.getJobDescription() + "; " + "familiar with autotest";}
}

JVMRequiremement(JVM要求):

public class JVMRequirement extends JobRequirement {Job job;public JVMRequirement(Job job) {this.job = job;}@Overridepublic String getTitle() {return job.getTitle();}@Overridepublic String getJobDescription() {return job.getJobDescription() + "; " + "familiar with JVM";}    
}

MajorRequirement(专业要求):

public class MajorRequirement extends JobRequirement {Job job;public MajorRequirement(Job job) {this.job = job;}@Overridepublic String getTitle() {return job.getTitle();}@Overridepublic String getJobDescription() {return job.getJobDescription() + "; " + "major in Computer Science";}
}

执行Main类:

 1 public class Main {
 2     public static void main(String[] args) {
 3         //develop 
 4         Job developer = new SoftwareDeveloper();
 5         developer = new MajorRequirement(developer);
 6         developer = new JVMRequirement(developer);
 7         System.out.println("Title: " + developer.getTitle());
 8         System.out.println("JD: " + developer.getJobDescription());
 9         //tester
10         Job tester = new SoftwareTester();
11         tester = new AutotestRequirement(new MajorRequirement(tester));
12         System.out.println("Title: " + tester.getTitle());
13         System.out.println("JD: " + tester.getJobDescription());
14     }
15 }

执行结果:

Title: Software Developer
JD: familiar with Java; major in Computer Science; familiar with JVM
Title: Software Tester
JD: familiar with test-analysis; major in Computer Science; familiar with autotest

可以看到,使用装饰者的代码非常简洁,SoftwareDeveloper本是一个普通的开发岗位,你可以通过加不同的装饰器给这个岗位增加特殊的要求。当有新的职位要求要加入时,只要创建新的requirement类来装饰即可。

二、Python中的装饰器

上一节介绍了OOP中的装饰器设计模式的思想和用法,下面简单谈谈Python中的装饰器。关于Python中的装饰器使用,这里不细讲,有兴趣可以直接查询廖雪峰的Python教程:《装饰器-廖雪峰的官方网站》。这里主要谈谈两者的区别:

1. Python中的装饰器实际上是基于函数的装饰,而面向对象的装饰器思想是基于类的装饰。

Python中的装饰器,实际上是通过语法实现基于函数的装饰,增强原有函数的功能。它通过将一些公有操作(比如:日志打印,校验网站session中是否已存在登录信息等)抽取出来,在各个需要这些公有操作的函数上方通过增加“@装饰器名”的方式来增强函数的功能。缺点是:当一个方法加上装饰器后,不能再调用原来的方法。

面向对象中的装饰器,是基于类的装饰。装饰者与被装饰者继承相同的父类,准确地应该说是有相同的“祖先”。它通过一系列的封装,使得更多的类的方法可以被复用。缺点:可能会有大量的类,造成API调用时的困扰。

2. 装饰器模式是一种设计思想,Python也是一种面向对象的语言,当然也可以使用面向对象的方式来实现装饰器模式。

三、Java I/O中的装饰者模式应用

 

上图是简单的InputStream类图(有些类没有完全列出),可以看到InputSream是一个父类,下面有4个子类,其中FileInputStream、StringBufferInputStream、ByteArrayInputStream都是被装饰者,是可以被装饰者包装起来的具体组件;FilterInputSream是一个抽象装饰者,下面有4个具体的装饰者类:PushbackInputStream、BufferedInputStream、DataInputStream、LineNumberInputStream。

这样一看,Java I/O的结构关系似乎就明了了许多,但是其中具体的细节,还是必须要抽时间系统地学习一番。

四、写在最后

其实对我来说,第一季度已经过去了70%,后续还有非常繁忙地迭代测试任务,没有多少时间可以用来完成自己第一季度的计划。在这个时间点,我更应该做的是去学习自己计划中的任务(YARN)。只是发现最近这周自己的思想状态不是很好,心态上似乎也有点浮躁,所以抽时间来写点东西,让自己的心静一静。另一方面也想将自己看过的东西实践并记录下来,可以方便后续使用时查阅。希望通过这篇随笔提醒自己,珍惜时间,不忘初心,方得始终。

转载于:https://www.cnblogs.com/znicy/p/6445359.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/372855.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

swift - 导航栏设置

话不多,直接贴代码: let nav UINavigationController.init(rootViewController: viewController) nav.topViewController?.title title// 设置导航栏的标题 nav.navigationBar.tintColor .whiteColor()// 设置push出的导航栏的返回颜色(箭头及文字) …

mysql5.6主从复制(读写分离)方案_MySQL5.6主从复制(读写分离)方案

MySQL5.6主从复制(读写分离)方案一、前言:为什么MySQL要做主从复制(读写分离)?通俗来讲,如果对数据库的读和写都在同一个数据库服务器中操作,业务系统性能会降低。为了提升业务系统性能,优化用户体验,可以通…

在实践中使用延迟队列

通常,在某些情况下,当您有某种工作或作业队列时,有必要不立即处理每个工作项或作业,而是要延迟一些时间。 例如,如果用户单击一个按钮来触发要完成的某项工作,而一秒钟后,用户意识到他/她错了&a…

PCL学习八叉树

建立空间索引在点云数据处理中有着广泛的应用,常见的空间索引一般 是自顶而下逐级划分空间的各种空间索引结构,比较有代表性的包括BSP树,KD树,KDB树,R树,四叉树,八叉树等索引结构,而…

Android实现自定义带文字和图片的Button

在Android开发中经常会需要用到带文字和图片的button,下面来讲解一下常用的实现办法。 一.用系统自带的Button实现 最简单的一种办法就是利用系统自带的Button来实现,这种方式代码量最小。在Button的属性中有一个是drawableLeft,这个 属性可以…

mysql语句中的注释方法_MySQL语句注释方式简介

MySQL支持三种注释方式:1.从‘#字符从行尾。2.从‘-- 序列到行尾。请注意‘-- (双破折号)注释风格要求第2个破折号后面至少跟一个空格符(例如空格、tab、换行符等等)。3.从/*序列到后面的*/序列。结束序列不一定在同一行中,因此该语法允许注释跨越多行。…

aqlserver实用程序_sqlserver命令提示实用工具的介绍

除上述的图形化管理工具外,SQL Server2008还提供了大量的命令行实用工具,包括bcp、dtexec、dtutil、osql、reconfig、sqlcmd、sqlwb和tablediff等,下面进行简要说明。dtexec实用工具用于配置和执行SQL Server2008 Intgration Services包。用户…

使用Java和Scala将Play Framework 2应用程序部署到Openshift

几个星期, 马克阿特伍德 ( Mark Atwood) , 豪尔赫阿里斯 ( Jorge Aliss )和我塞巴斯蒂安 斯卡塔诺 ( SebastinScarano)参加了红帽网络研讨会LETS PLAY! 在云端&#xff1…

LintCode 387: Smallest Difference

LintCode 387: Smallest Difference 题目描述 给定两个整数数组(第一个是数组A,第二个是数组B),在数组A中取A[i],数组B中取B[j],A[i]和B[j]两者的差越小越好(|A[i] - B[j]|)。返回最小差。 样例 给定数组A …

android框架----下沉文字Titanic的使用

Titanic is a simple illusion obtained by applying an animated translation on the TextView TextPaint Shaders matrix. Titanic的使用 Titanic的使用,项目结构如下: 一、下载Titanic并且部署到项目中 Titanic的项目地址: https://github…

linux 自动安装mysql_Linux安装mysql

一、下载这里我创建了一目录software用于存放我们待会要下载的mysql包,先去到该目录命令:cd /software命令:wget http://mirrors.sohu.com/mysql/MySQL-5.7/mysql-5.7.17-linux-glibc2.5-x86_64.tar下载完成后,你会在software这个…

Quartz Scheduler插件–隐藏的宝藏

尽管在官方文档中进行了简要描述,但我相信Quartz插件了解得还不够多,看看它们有多有用。 本质上,Quartz中的插件是方便的类,用于包装基础侦听器的注册。 您可以自由编写自己的插件,但我们将专注于Quartz随附的现有插件…

mysql查询表名匹配只有字母的_MySQL按某些匹配字母查询表

MySQL查询是MySQL的核心功能,有时候我们需要查找带有某些匹配字母的表。下文对该MySQL查询方式作了详细的介绍,供您参考。在MySQL中我们可以使用LIKE或者NOT LIKE操作符进行比较。在MySQL中模式默认是不区分大小写的。查询示例,student表----…

hdu 1181(Floyed)

变形课 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 20748 Accepted Submission(s): 7494 Problem Description呃......变形课上Harry碰到了一点小麻烦,因为他并不像Hermione那样能够记住所有的咒语而随意的…

读书笔记-你不知道的JS上-混入与原型

继承 mixin混合继承 function mixin(obj1, obj2) {for (var key in obj2) {//重复不复制if (!(key in obj1)) {obj1[key] obj2[key];}}return obj1;} 这种复制是浅复制,对象或者数组函数等都是同一个引用,改变obj1的会同时影响obj2。 寄生继承 ... 隐式…

JUnit和Hamcrest:在assertEquals上进行改进

在我的博客文章中,Java越来越接受静态导入吗? ,我讨论了在Java中越来越多地使用静态导入来使代码在某些情况下更流畅。 Java 单元测试特别受静态导入的影响,在此博客文章中,我提供了一个简单的示例,说明如何…

mysql delete temporary denied_这些错误是什么意思?djang中的mysql

我试着运行一个程序,我被给予了一个例子,它就像一个购物网站,使用MySQL数据库而不是Django提供的原始数据库!我只是想看看有没有人理解这些错误的含义?任何信息都将不胜感激!我本可以提供网页的代码&#x…

C语言 · 芯片测试

基础练习 芯片测试 时间限制:1.0s 内存限制:512.0MB问题描述有n(2≤n≤20)块芯片,有好有坏,已知好芯片比坏芯片多。每个芯片都能用来测试其他芯片。用好芯片测试其他芯片时,能正确给出被测试…

Animation用法

测试代码及说明&#xff1a; <!DOCTYPE html> <html lang"en-US"> <head><meta charset"UTF-8"><title>Simple CSS3 Animation</title><style type"text/css">#demo {position: absolute;left: 30%;t…

mysql dese_MySQL 5.6-类似于DENSE_RANK的功能,无需订购

小编典典对于 MySQL版本<8.0(OP的版本是5.6)&#xff1a;问题陈述看起来需要DENSE_RANK功能groupVarian; 但是事实并非如此。正如 GordonLinoff解释的那样 &#xff1a;您似乎希望按它们在数据中出现的顺序来枚举它们。假设您的表名是t(请为您的代码相应地更改表名和字段名)…