多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > php教程 > 《重構》第一章示例 ― 體驗重構的魔力 RefactorSample

《重構》第一章示例 ― 體驗重構的魔力 RefactorSample

來源:程序員人生   發布時間:2015-02-27 08:01:01 閱讀次數:2428次

       實驗室已坐定了,環境和氛圍很好,今天老師請來了北京卓爾的孫經理,聊了很多,最大的意外是,任老師是云計算出身,棒,java以后必定是要接觸云計算的。

1個月了,沒有認真寫博客,也沒有認真學習,數據庫的學習進度1直拖拖拉拉到現在也沒有弄定,sad。。。接了1個任務,寫1個基于Web的實驗室內部的管理系統,拿來練手,以后就是企業項目1個CC呼喚中心的1模塊,對接卓爾,第1次接觸實際項目,還甚么都不會,激動卻又忐忑。但,再1起重新燃起了學習的熱火,來吧。


今天,看了1下《重構》的第1章,深深的被吸引了....

Let‘s go,1起走進重構的世界吧!


示例 

情形:顧客租電影,電影分3種,兒童票,普通片,新片,兒童片2天之內1.5元,超過兩天,每天加收1.5元,普通片3天之內2元,超過兩天,每天加收2元,新片每天3元,每租1次電影積分加1,如果是新片,且租期超過2天,積分加2。

分析:

以面向對象的思想分析,觸及對象顧客,影片,外加1個租賃類作為顧客和影片的橋接

編寫代碼

影片類(Movie):

public class Movie { public static final int CHILDRENS = 0; public static final int REGULARS = 1; public static final int NEW_RELEASE = 2; private String name; private int movType; public Movie(String name, int movType) { this.name = name; this.movType = movType; } name: set 和 get 方法 movType: set 和get 方法 }

為了節省篇幅,Movie類的name、movType的set和get就不貼了。

租賃類(Rental):

public class Rental { private Movie movie; private int rentDays; public Rental(Movie movie,int rentDays) { this.movie = movie; this.rentDays = rentDays; } movie 和 rentDays的set和get方法

顧客類(Customer):

public class Customer { private String name; private ArrayList<Rental> rentals = new ArrayList<Rental>(); public Customer(String name) { this.name = name; } public void addRent(Rental r){ rentals.add(r); } public String getName() { return name; } public void setName(String name) { this.name = name; } public String statement() throws Exception { String result = "Rental report for " + getName() + " "; double totalAmount = 0; int frequent = 0; for(Rental r : rentals){ double thisAmount = 0; switch (r.getMovie().getMovType()){ case Movie.CHILDRENS : thisAmount += (r.getRentDays()>2)?((r.getRentDays()⑵)*1.5+1.5):1.5; break; case Movie.REGULARS: thisAmount += (r.getRentDays()>3)?((r.getRentDays()⑶)*2+2):2; break; case Movie.NEW_RELEASE: thisAmount += r.getRentDays() * 3; break; default:throw new Exception("類型異常"); } totalAmount += thisAmount; frequent += (r.getMovie().getMovType()==Movie.NEW_RELEASE && r.getRentDays()>2)?2:1; result+=" " + r.getMovie().getName() + " " + String.valueOf(thisAmount) + " "; } result += "Amount is " + String.valueOf(totalAmount) + "元 "; result += "frequent is " + String.valueOf(frequent)+"分"; return result; } }

編寫測試代碼:

public class Test { public static void main(String[] args) throws Exception { Movie m1 = new Movie("葫蘆娃",0);//兒童片 Movie m2 = new Movie("神雕俠侶",1);//普通片 Movie m3 = new Movie("何以笙簫默",2);//新片 Customer c = new Customer("朱小妹"); c.addRent(new Rental(m1,2));//1.5 c.addRent(new Rental(m2,2));//2 c.addRent(new Rental(m3,3));//9 System.out.println(c.statement()); } }

以上代碼完成了示例需求,但是代碼寫的...太爛了,我自己寫絕對也是這個模樣。。。代碼爛,怎樣辦?重構!

第1步:1勞永逸 ―  修改測試代碼


為了方便測試,我們將打印結果作為1個字符串保存起來。

public class Test { public static void main(String[] args) throws Exception { Movie m1 = new Movie("葫蘆娃",0);//兒童片 Movie m2 = new Movie("神雕俠侶",1);//普通片 Movie m3 = new Movie("何以笙簫默",2);//新片 Customer c = new Customer("朱小妹"); c.addRent(new Rental(m1,2));//1.5 c.addRent(new Rental(m2,2));//2 c.addRent(new Rental(m3,3));//9 String result = "Rental report for 朱小妹 " + " 葫蘆娃 1.5 " + " 神雕俠侶 2.0 " + " 何以笙簫默 9.0 " + "Amount is 12.5元 " + "frequent is 4分"; System.out.println(c.statement().equals(result)); } }

以后的測試結果,true就是修改正確,false就是修改失敗。


第2步:1石2鳥  ―  分解customer類statement方法


縱觀所有代碼,惟獨customer類的statement代碼最多,最亂,看著煩,看switch更煩,而switch的作用就是1個計算1個臨時變量thisAmount的作用,而臨時變量越多對1個程序來講就越容易出錯,既然容易出錯,totalAmount和frement有甚么用,還占地方,留它們干嗎,拿走,單獨封裝。

更改后的customer類:

public class Customer { private String name; private ArrayList<Rental> rentals = new ArrayList<Rental>(); public Customer(String name) { this.name = name; } public void addRent(Rental r){ rentals.add(r); } public String getName() { return name; } public void setName(String name) { this.name = name; } public String statement() throws Exception { String result = "Rental report for " + getName() + " "; for (Rental r : rentals ) { result += " " + r.getMovie().getName() + " " + String.valueOf(amountFor(r)) + " "; } result += "Amount is " + String.valueOf(getTotalAmount()) + "元 "; result += "frequent is " + String.valueOf(getTotalFrequent())+"分"; return result; } private double getTotalAmount() throws Exception { double totalAmount = 0; for(Rental r : rentals){ totalAmount += amountFor(r); } return totalAmount; } private int getTotalFrequent(){ int frequent = 0; for(Rental r : rentals){ frequent += (r.getMovie().getMovType()==Movie.NEW_RELEASE && r.getRentDays()>2)?2:1; } return frequent; } private double amountFor(Rental r) throws Exception { double thisAmount = 0; switch (r.getMovie().getMovType()){ case Movie.CHILDRENS : thisAmount += (r.getRentDays()>2)?((r.getRentDays()⑵)*1.5+1.5):1.5; break; case Movie.REGULARS: thisAmount += (r.getRentDays()>3)?((r.getRentDays()⑶)*2+2):2; break; case Movie.NEW_RELEASE: thisAmount += r.getRentDays() * 3; break; default:throw new Exception("類型異常"); } return thisAmount; } }


這樣statement方法龐大和臨時變量多的問題都解決了,進行測試,true,修改正確

第3步:各回各家 ― 做自己該干的事


重新審視1下customer類,你會發現它很多它不該干的事,switch計算單次租賃花費和積分這個事,應當電影類干吧,花多錢,很多少分,電影本身最清楚

問題還是存在switch身上,最好不要在另外一個對象的屬性基礎上應用switch,如果非要使用,也應當是在對象自己的數據上使用,而不是在他人的數據上使用。

在rental類中增加getOneMoney方法和getOneFre方法,customer類刪除amountFor方法,修改getTotalFrequent方法,switch搬家到Movie類中

更改后的customer類

只變動了getTotalFrequent方法for循環

public class Customer { private String name; private ArrayList<Rental> rentals = new ArrayList<Rental>(); public Customer(String name) { this.name = name; } public void addRent(Rental r){ rentals.add(r); } public String getName() { return name; } public void setName(String name) { this.name = name; } public String statement() throws Exception { String result = "Rental report for " + getName() + " "; for (Rental r : rentals ) { result += " " + r.getMovie().getName() + " " + String.valueOf(r.getOne()) + " "; } result += "Amount is " + String.valueOf(getTotalAmount()) + "元 "; result += "frequent is " + String.valueOf(getTotalFrequent())+"分"; return result; } private double getTotalAmount() throws Exception { double totalAmount = 0; for(Rental r : rentals){ totalAmount += r.getOne(); } return totalAmount; } private int getTotalFrequent(){ int frequent = 0; for(Rental r : rentals){ frequent += r.getOneFre(); } return frequent; } }

更改后的rental,起了1個橋梁作用

public class Rental { private Movie movie; private int rentDays; public Rental(Movie movie,int rentDays) { this.movie = movie; this.rentDays = rentDays; } public int getRentDays() { return rentDays; } public void setRentDays(int rentDays) { this.rentDays = rentDays; } public Movie getMovie() { return movie; } public double getOne() throws Exception { return getMovie().getMoney(rentDays) ; } public int getOneFre(){ return getMovie().getFrequent(rentDays); } public void setMovie(Movie movie) { this.movie = movie; } }

更改后的movie類,終究開始做事了

/** * Created by Kevy on 2015/1/21. */ /*編寫電影類代碼*/ public class Movie { public static final int CHILDRENS = 0; public static final int REGULARS = 1; public static final int NEW_RELEASE = 2; private String name; private int movType; public Movie(String name, int movType) { this.name = name; this.movType = movType; } public int getMovType() { return movType; } public void setMovType(int movType) { this.movType = movType; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getMoney(int RentDays) throws Exception { double thisAmount = 0; switch (getMovType()){ case Movie.CHILDRENS : thisAmount += (RentDays>2)?((RentDays⑵)*1.5+1.5):1.5; break; case Movie.REGULARS: thisAmount += (RentDays>3)?((RentDays⑶)*2+2):2; break; case Movie.NEW_RELEASE: thisAmount += RentDays * 3; break; default:throw new Exception("類型異常"); } return thisAmount ; } public int getFrequent(int RentDays){ return (getMovType()==NEW_RELEASE && RentDays>2)?2:1; } }

測試OK,沒有問題。


第4步 利用多態

現在所有的類,都在干自己的事,movie類的getMoney方法的代碼量看著還是不太好,既然是3種電影只是類型不同而已,那末久完全可以向上抽取使用抽象類

public interface Type { public int getType(); public double getMovMeony(int days); }

public class ChildrenMov implements Type { public int getType() { return 0; } public double getMovMeony(int days) { return (days>2)?((days⑵)*1.5+1.5):1.5; } }

public class RegularMov implements Type { public int getType() { return 1; } public double getMovMeony(int days) { return (days>3)?((days⑶)*2+2):2; } }

public class NewMov implements Type { public int getType() { return 2; } public double getMovMeony(int days) { return days * 3; } }

終究完全代碼:

import java.util.ArrayList; /** * Created by Kevy on 2015/1/21. */ public class Customer { private String name; private ArrayList<Rental> rentals = new ArrayList<Rental>(); public Customer(String name) { this.name = name; } public void addRent(Rental r){ rentals.add(r); } public String getName() { return name; } public void setName(String name) { this.name = name; } public String statement() throws Exception { String result = "Rental report for " + getName() + " "; for (Rental r : rentals ) { result += " " + r.getMovie().getName() + " " + String.valueOf(r.getOne()) + " "; } result += "Amount is " + String.valueOf(getTotalAmount()) + "元 "; result += "frequent is " + String.valueOf(getTotalFrequent())+"分"; return result; } private double getTotalAmount() throws Exception { double totalAmount = 0; for(Rental r : rentals){ totalAmount += r.getOne(); } return totalAmount; } private int getTotalFrequent(){ int frequent = 0; for(Rental r : rentals){ frequent += r.getOneFre(); } return frequent; } }

/** * Created by Kevy on 2015/1/21. */ public class Rental { private Movie movie; private int rentDays; public Rental(Movie movie,int rentDays) { this.movie = movie; this.rentDays = rentDays; } public int getRentDays() { return rentDays; } public void setRentDays(int rentDays) { this.rentDays = rentDays; } public Movie getMovie() { return movie; } public double getOne() throws Exception { return getMovie().getMoney(rentDays) ; } public int getOneFre(){ return getMovie().getFrequent(rentDays); } public void setMovie(Movie movie) { this.movie = movie; } }

/** * Created by Kevy on 2015/1/21. */ /*編寫電影類代碼*/ public class Movie { public static final int CHILDRENS = 0; public static final int REGULARS = 1; public static final int NEW_RELEASE = 2; private String name; private Type t; public Movie(String name, int movType) throws Exception { this.name = name; setT(movType); } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getMoney(int RentDays) { return t.getMovMeony(RentDays); } public int getFrequent(int RentDays){ return (t.getType()==NEW_RELEASE && RentDays>2)?2:1; } public void setT(int d) throws Exception { switch (d){ case CHILDRENS :t = new ChildrenMov(); break; case REGULARS:t = new RegularMov(); break; case NEW_RELEASE:t = new NewMov(); break; default:throw new Exception("類型毛病"); } } }

import sun.plugin2.message.ModalityChangeMessage; /** * Created by Kevy on 2015/1/21. */ /* 編寫測試代碼 */ public class Test { public static void main(String[] args) throws Exception { Movie m1 = new Movie("葫蘆娃",0);//兒童片 Movie m2 = new Movie("神雕俠侶",1);//普通片 Movie m3 = new Movie("何以笙簫默",2);//新片 Customer c = new Customer("朱小妹"); c.addRent(new Rental(m1,2));//1.5 c.addRent(new Rental(m2,2));//2 c.addRent(new Rental(m3,3));//9 String result = "Rental report for 朱小妹 " + " 葫蘆娃 1.5 " + " 神雕俠侶 2.0 " + " 何以笙簫默 9.0 " + "Amount is 12.5元 " + "frequent is 4分"; System.out.println(c.statement().equals(result)); } }

至此,1個簡單的代碼重構示例,重構終了

重構最大的啟發就是:測試、小改、測試、小改....


生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 波多野结衣视频一区二区 | 冲田杏梨j和l超乳w真性中出 | 爽好舒服快奶水视频 | 免费一区区三区四区 | 爽好舒服快奶水视频 | 国产精品久久久久久搜索 | 久久性生大片免费观看性 | a色在线| 国产在线每日更新 | 亚洲理论a中文字幕在线 | 久久受www免费人成_看片中文 | 一级aaaaaa毛片免费同男同女 | 国产一区日韩二区欧美三 | 五月激情五月婷婷 | 亚洲精品亚洲人成人网 | 国产成人精品免费视频大全办公室 | 国产淫| 国产欧美一区二区久久 | 黄色网址在线看 | 伊人香焦 | 性欧美video超清 | 成人欧美一区二区三区黑人 | 中文国产成人精品久久一 | 国产大片免费观看中文字幕 | 久久久久久久国产精品 | 久久国产精品亚洲一区二区 | 亚洲www在线| 性色影院| 手机成人在线视频 | 一区二区成人国产精品 | 国产乱码精品一区二区三 | 国产福利视频一区二区 | 爱爱日韩 | 日本高清免费视频色www | japan高清日本乱xxxx | 色妞色综合久久夜夜 | 欧美成人第一页 | 国产精品v| 亚洲欧美成人中文在线网站 | 手机看片国产免费久久网 | 武则天全黄肉体毛片免费看 |