自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

《重構(gòu)之美》之改造面向過(guò)程式設(shè)計(jì)

開發(fā) 開發(fā)工具
我們將看到的是重構(gòu)之美的改造面向過(guò)程式設(shè)計(jì)問(wèn)題,希望這些能對(duì)大家有所幫助。

使用面向?qū)ο笳Z(yǔ)言進(jìn)行過(guò)程式設(shè)計(jì)的例子,可謂俯拾皆是??催@段代碼:

  1. public class SyncExecutor {   
  2.     public void executeSync() {   
  3.         syncSchools();   
  4.         syncGrades();   
  5.         syncFaculties();   
  6.     }   

這段代碼很清晰,分別執(zhí)行了對(duì)學(xué)校、年級(jí)與教師信息的同步。一目了然,似乎沒有什么問(wèn)題。然而,如果深入閱讀各個(gè)同步子方法,就會(huì)發(fā)現(xiàn)某種壞味道,那就是重復(fù)代碼。

  1. private void syncSchools() {   
  2.     List<School> sourceSchools = getSourceSchools();   
  3.     List<School> targetSchools = new ArrayList<School>();   
  4.     List<String> sourceSchoolCodes = getSchoolCodes(sourceSchools);   
  5.     Map<String,School> targetSchoolWithCodeMapping = schoolService.getSchoolWithCodeMapping(sourceSchoolCodes);   
  6.     for (School sourceSchool:sourceSchools) {   
  7.         String schoolCode = sourceSchool.getSchoolCode();   
  8.         School targetSchool = targetSchoolWithCodeMapping.get(schoolcode);   
  9.         if (targetSchool == null) {   
  10.             targetSchool = new School(   
  11.                 sourceSchool.getSchoolCode(),   
  12.                 sourceSchool.getSchoolName(),   
  13.                 sourceSchool.getProvinceCode(),   
  14.                 sourceSchool.getSchoolAddress(),   
  15.                 sourceSchool.getSchoolZip(),   
  16.                 sourceSchool.getSchoolTel());   
  17.         } else if (isCover) {   
  18.             targetSchool.setSchoolCode(sourceSchool.getSchoolCode());   
  19.             targetSchool.setSchoolName(sourceSchool.getSchoolName());   
  20.             targetSchool.setProvinceCode(sourceSchool.getProvinceCode());   
  21.             targetSchool.setSchoolAddress(sourceSchool.getSchoolAddress());   
  22.             targetSchool.setSchoolZip(sourceSchool.getSchoolZip());   
  23.             targetSchool.setSchoolTel(sourceSchool.getSchoolTel());   
  24.         }   
  25.             targetSchools.add(targetSchool);   
  26.     }  
  27.  
  28.     syncService.saveOrUpdate(targetSchools);   
  29. }   
  30. private void syncGrades() {   
  31.     List<Grade> sourceGrades = getSourceGrades();   
  32.     List<Grade> targetGrades = new ArrayList<Grade>();   
  33.     List<String> sourceGradeCodes = getGradeCodes(sourceGrades);   
  34.     Map<String,Grade> targetGradeWithCodeMapping = gradeService.getGradeWithCodeMapping(sourceGradeCodes);   
  35.     for (Grade sourceGrade:sourceGrades) {   
  36.         String gradeCode = sourceGrade.getGradeCode();   
  37.         Grade targetGrade = targetGradeWithCodeMapping.get(gradeCode);   
  38.         if (targetGrade == null) {   
  39.             targetGrade = new Grade(   
  40.                 sourceGrade.getGradeCode(),   
  41.                sourceGrade.getName(),   
  42.                 sourceGrade.getEntranceDay(),   
  43.                 sourceGrade.getGraduateDay(),   
  44.                 sourceGrade.getSchoolCode(),   
  45. sourceGrade.getSchoolProperty());   
  46.         } else if (isCover) {   
  47.             targetGrade.setGradeCode(sourceGrade.getGradeCode());   
  48.             targetGrade.setName(sourceGrade.getName());   
  49.             targetGrade.setEntranceDay(sourceGrade.getEntranceDay());   
  50.             targetGrade.setGraduateDay(sourceGrade.getGraduateDay());   
  51.             targetGrade.setSchoolCode(sourceGrade.getSchoolCode());   
  52.             targetGrade.setSchoolProperty(sourceGrade.getSchoolProperty());   
  53.         }   
  54. targetGrades.add(targetGrade);   
  55.     }  
  56.  
  57.     syncService.saveOrUpdate(targetGrades);   

當(dāng)然,真實(shí)的代碼更加復(fù)雜與混亂,但如果經(jīng)過(guò)一系列重構(gòu),例如Rename Method,Extract Method之后,就會(huì)變得逐漸清晰,大體結(jié)構(gòu)如上述展示的代碼。閱讀這樣的代碼,是否發(fā)現(xiàn)各個(gè)同步子方法均有似曾相識(shí)的感覺呢?究其原因,在于同步的執(zhí)行邏輯大體相似,換言之,它們具有相似的模板。我們需要改善其結(jié)構(gòu),實(shí)現(xiàn)代碼的重用。然而,在方法層面上,我們已很難實(shí)現(xiàn)這一點(diǎn)。事實(shí)上,當(dāng)我們?cè)诰帉懲椒椒〞r(shí),已經(jīng)落入了過(guò)程式設(shè)計(jì)的窠臼。我們首先想到的是執(zhí)行的過(guò)程,而非對(duì)象。現(xiàn)在,我們需要將這些執(zhí)行過(guò)程封裝為對(duì)象,充分地利用繼承等機(jī)制實(shí)現(xiàn)類級(jí)別的重用。顯然,這里可以運(yùn)用Form Template Method重構(gòu)。當(dāng)然,在此之前,我們還需要運(yùn)用Extract Superclass,對(duì)School、Grade等類進(jìn)行一系列重構(gòu),例如為它們建立共同的父類Entity,提供getCode()方法。并運(yùn)用Rename Method,將原來(lái)各自實(shí)體類的相關(guān)方法,例如getSchoolCode()、getGradeCode()等,更名為getCode()。

現(xiàn)在,我們需要為同步操作定義一個(gè)共同的抽象類DataSynchronizer,然后利用Move Method重構(gòu),將原有SyncExecutor的相關(guān)代碼搬移到DataSynchronizer中:

  1. public abstract class DataSynchronizer {   
  2.     public void execute() {   
  3.         List<Entity> sourceEntities = getSourceEntities();   
  4.         List<Entity> targetEntities = new ArrayList<Entity>();   
  5.         List<String> sourceEntityCodes = getEntityCodes(sourceEntities);   
  6.         Map<String,Entity> targetEntityWithCodeMapping = getEntityWithCodeMapping(sourceEntityCodes);   
  7.         for (Entity sourceEntity:sourceEntities) {   
  8.             String entityCode = sourceEntity.getCode();   
  9.             Entity targetEntity = targetEntityWithCodeMapping.get(entityCode);   
  10.             if (targetEntity == null) {   
  11.                 targetGrade = createEntity(sourceEntity);   
  12.             } else if (isCover) {   
  13.                 updateEntity(targetEntity,sourceEntity);   
  14.             }   
  15.             targetEntities.add(targetEntity);   
  16.         }  
  17.  
  18.         syncService.saveOrUpdate(targetEntities);   
  19.     }  
  20.  
  21.     protected abstract List<Entity> getSourceEntities();   
  22.     protected abstract List<String> getEntityCodes(List<Entity> entities);   
  23.     protected abstract Map<String,Entity> getEntityWithCodeMapping(List<String> entityCodes);   
  24.     protected abstract Entity createEntity(Entity sourceEntity);   
  25.     protected abstract void updateEntity(Entity target, Entity source);   

注意,在獲得Entity與Code的Map對(duì)象時(shí),我對(duì)原有的代碼實(shí)現(xiàn)進(jìn)行了封裝,因?yàn)椴煌膶?shí)體同步類,所要調(diào)用的Service對(duì)象是不一樣的。因此,需要將調(diào)用Service相關(guān)方法的實(shí)現(xiàn)留給子類?,F(xiàn)在,只需要定義各個(gè)同步類繼承DataSynchronizer,重寫相關(guān)的受保護(hù)抽象方法即可:

  1. public class SchoolSynchronizer extends DataSynchronizer{}   
  2. public class GradeSynchronizer extends DataSynchronizer{}   
  3. public class FacultySynchronizer extends DataSynchronizer{} 

接著,修改SyncExecutor類的實(shí)現(xiàn)。為方便調(diào)用同步子類的相關(guān)方法,我定義了一個(gè)Factory Method:

  1. public class SyncExecutor {   
  2.     public void executeSync() {   
  3.         for (DataSynchronizer dataSync:createSynchronizers()) {   
  4.             dataSync.execute();   
  5.         }   
  6.     }  
  7.  
  8.     protected List<DataSynchronizer> createSynchronizers() {   
  9.         List< DataSynchronizer> synchronizers =   
  10. new ArrayList< DataSynchronizer();   
  11.         synchronizers.add(new SchoolSynchronizer());   
  12.         synchronizers.add(new GradeSynchronizer());   
  13. synchronizers.add(new FacultySynchronizer());  
  14.  
  15. return synchronizers;   
  16.     }   

以真正面向?qū)ο蟮姆绞絹?lái)完成上述功能,無(wú)論在代碼結(jié)構(gòu)、重用性還是擴(kuò)展性方面,比諸之前的實(shí)現(xiàn),都有了長(zhǎng)足的改善。這就是面向?qū)ο笤O(shè)計(jì)的優(yōu)雅之處。

縱觀整個(gè)重構(gòu)過(guò)程,實(shí)際上,我在運(yùn)用Convert Procedural Design to Objects重構(gòu)時(shí),大量運(yùn)用了Rename Method、Extract Method、Move Method、Extract Superclass、Form Template Method等重構(gòu)手法。這是合乎常情的。當(dāng)我們?cè)趯?duì)程序進(jìn)行重構(gòu)時(shí),往往需要運(yùn)用各種重構(gòu)手法,才能達(dá)到最終的重構(gòu)目的。對(duì)于大型重構(gòu)而言,這種特征尤其明顯。

原文鏈接:http://www.cnblogs.com/wayfarer/archive/2010/12/23/1914530.html

【編輯推薦】

  1. 重構(gòu)Struts2 JSP分頁(yè)
  2. 在大型遺留系統(tǒng)基礎(chǔ)上運(yùn)作重構(gòu)項(xiàng)目
  3. 重構(gòu)和靜態(tài)分析被添加進(jìn)Data Dude工具
  4. 學(xué)習(xí)筆記 UML面向?qū)ο蠹夹g(shù)概述
  5. C++中的面向?qū)ο缶幊毯?jiǎn)介
責(zé)任編輯:彭凡 來(lái)源: 博客園
相關(guān)推薦

2011-07-10 16:04:01

程序員

2010-07-15 13:56:24

面向?qū)ο?/a>面向過(guò)程

2009-09-27 14:12:12

面向?qū)ο笤O(shè)計(jì)單一職責(zé)

2021-08-03 08:13:48

重構(gòu)API代碼

2011-03-31 09:32:25

EclipseRefactor

2023-12-08 07:59:41

對(duì)象設(shè)計(jì)設(shè)計(jì)模式軟件設(shè)計(jì)

2021-02-06 08:34:49

函數(shù)memoize文檔

2021-07-08 06:08:54

架構(gòu)重構(gòu)開發(fā)

2010-08-09 10:39:14

FlexACtionSCrip

2013-12-09 13:17:35

命令ping

2019-06-13 11:50:41

Python面向?qū)ο?/a>編程語(yǔ)言

2017-11-28 17:44:28

匠心

2011-04-11 10:14:47

HTML 5

2021-08-04 08:56:34

語(yǔ)言Go排序

2011-07-11 21:54:55

工作站解決方案

2021-06-09 09:06:52

Go語(yǔ)言算法

2014-08-28 09:49:56

麗晶軟件信息化

2022-08-02 08:07:24

單元測(cè)試代碼重構(gòu)

2011-07-05 14:42:46

java

2011-04-28 11:21:58

音響家庭影院
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)