設計模式學習(三)——裝飾器模式

前言

距離上一次正兒八經地寫隨筆已經有一段時間了,雖然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.pswp.cn/news/372855.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/372855.shtml
英文地址,請注明出處:http://en.pswp.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(請為您的代碼相應地更改表名和字段名)…