zoukankan      html  css  js  c++  java
  • 设计模式学习(三)——装饰器模式

    前言

    距离上一次正儿八经地写随笔已经有一段时间了,虽然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");
        }
        @Override
        public String getJobDescription() {
            return "familiar with Java";
        }
    }

    SoftwareTester(职位2)

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

    AutotestRequirement(自动化测试要求):

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

    JVMRequiremement(JVM要求):

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

    MajorRequirement(专业要求):

    public class MajorRequirement extends JobRequirement {
        Job job;
        public MajorRequirement(Job job) {
            this.job = job;
        }
        @Override
        public String getTitle() {
            return job.getTitle();
        }
        @Override
        public 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)。只是发现最近这周自己的思想状态不是很好,心态上似乎也有点浮躁,所以抽时间来写点东西,让自己的心静一静。另一方面也想将自己看过的东西实践并记录下来,可以方便后续使用时查阅。希望通过这篇随笔提醒自己,珍惜时间,不忘初心,方得始终。

  • 相关阅读:
    HTTP
    HTTP
    Tomcat
    Tomcat
    时下流行的9种恶意软件,你都了解吗?
    MYSQL中表级锁、行级锁、页级锁介绍
    MYSQL中表级锁、行级锁、页级锁介绍
    MYSQL存储引擎笔记
    MYSQL存储引擎笔记
    Shell脚本案例:批量新增用户
  • 原文地址:https://www.cnblogs.com/znicy/p/6445359.html
Copyright © 2011-2022 走看看