日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

《重构-改善既有代码的设计》-第1例:租赁影片(2)

發(fā)布時(shí)間:2023/12/18 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《重构-改善既有代码的设计》-第1例:租赁影片(2) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前些天發(fā)現(xiàn)了一個(gè)巨牛的人工智能學(xué)習(xí)網(wǎng)站,通俗易懂,風(fēng)趣幽默,忍不住分享一下給大家。點(diǎn)擊跳轉(zhuǎn)到教程。

上接 ?重構(gòu)-改善既有代碼的設(shè)計(jì)-第1例:租賃影片(1)

?

2 ?運(yùn)用多態(tài)取代與價(jià)格相關(guān)的條件邏輯

?

2.1 最好不要在另一個(gè)對象的屬性基礎(chǔ)上運(yùn)用switch語句,應(yīng)該在對象自己的數(shù)據(jù)上使用。

2.1.1 移動(dòng) getCharge ,getFrequentRenterPoints 方法到Movie 類中去。把會(huì)根據(jù)影片類型的變化而變化的東西放在影片類中。

Movie 類改為:

?

package bean;/*** 影片* @author Administrator*/ public class Movie {public static final int CHILDRENS = 2; // 兒童片public static final int REGULAR = 0; // 普通片public static final int NEW_RELEASE = 1; // 新片private String _title;private int _priceCode;public Movie(String _title, int _priceCode) {this._title = _title;this._priceCode = _priceCode;}public int getPriceCode() {return _priceCode;}public void setPriceCode(int _priceCode) {this._priceCode = _priceCode;}public String getTitle() {return _title;}/*** 計(jì)算租金* @param dayRented 租賃天數(shù)* @return*/double getCharge(int dayRented){double result = 0; // 租金// 確定每種片子的租金switch(getPriceCode()){case Movie.REGULAR:result += 2;if(dayRented > 2 ){result += (dayRented - 2) * 1.5;}break;case Movie.NEW_RELEASE:result += dayRented*3;break;case Movie.CHILDRENS:result += 1.5;if(dayRented > 3 ){result += (dayRented - 3) * 1.5;}break;}return result;}/*** 常客積分計(jì)算* @param dayRented 租賃天數(shù)* @return*/int getFrequentRenterPoints(int dayRented){// (新片+租賃時(shí)間達(dá)2天 積分+1 )if(getPriceCode() == Movie.NEW_RELEASE && dayRented > 1){return 2;}else{return 1;}}}

?

?

?

?

?

?

2.1.2 修改Rental 類中的 ?getCharge ,getFrequentRenterPoints方法,讓它調(diào)用Movie 類提供的新函數(shù)。

?

Rental 類中的計(jì)算租金方法和??头e分計(jì)算方法 改為:

?

/*** ??头e分計(jì)算* @return*/int getFrequentRenterPoints(){return _movie.getFrequentRenterPoints(_daysRented);}/*** 計(jì)算租金* @return*/double getCharge(){return _movie.getCharge(_daysRented);}

?

?

?

?

?

2.2 ?為了確保任何時(shí)候都要通過取值函數(shù)和賦值函數(shù)來訪問 不愿意被外界直接訪問的屬性,我們用一個(gè)對賦值函數(shù)的調(diào)用來代替構(gòu)造中的部分代碼。

Movie 類的構(gòu)造之前為:

?

private String _title;private int _priceCode;public Movie(String _title, int _priceCode) {this._title = _title;this._priceCode = _priceCode;}public int getPriceCode() {return _priceCode;}public void setPriceCode(int _priceCode) {this._priceCode = _priceCode;}public String getTitle() {return _title;}


讓構(gòu)造不能直接訪問?不愿意被外界直接訪問的屬性,構(gòu)造現(xiàn)在改為:

?

?

public Movie(String _title, int _priceCode) {this._title = _title;setPriceCode(_priceCode);}

?

?

?

?

?

2.3 有新需求到來,有新品種影片,租金計(jì)算又有新算法 。

用到設(shè)計(jì)模式的狀態(tài)模式State(對象行為型)。

于是新建一個(gè)Price抽象類,并在其內(nèi)給2個(gè)抽象方法用于獲取影片的計(jì)價(jià)類型和計(jì)算租金,積分計(jì)算。

再寫多個(gè)子類繼承Price并各自實(shí)現(xiàn)父類方法以實(shí)現(xiàn)對租金計(jì)算,積分計(jì)算的重構(gòu)。

?2.3.1 Price 及子類 :

?

package bean;/*** 租金* @author Administrator*/ public abstract class Price {abstract int getPriceCode(); }

?

package bean;/*** 兒童片租金* @author Administrator*/ public class ChildrensPrice extends Price {@Overrideint getPriceCode() {return Movie.CHILDRENS;}}

?

package bean;public class NewReleasePrice extends Price {@Overrideint getPriceCode() {return Movie.NEW_RELEASE;}}

?

package bean;/*** 普通片租金* @author Administrator*/ public class RegularPrice extends Price {@Overrideint getPriceCode() {return Movie.REGULAR;}}

?

?

?

?

?

2.3.2 ?修改Movie ?類的計(jì)價(jià)類型屬性為Price類型,并改寫賦值函數(shù) :

?

package bean;/*** 影片* @author Administrator*/ public class Movie {public static final int CHILDRENS = 2; // 兒童片public static final int REGULAR = 0; // 普通片public static final int NEW_RELEASE = 1; // 新片private String _title;private Price _price; public Movie(String _title, int _priceCode) {this._title = _title;setPriceCode(_priceCode);}public int getPriceCode() {return _price.getPriceCode();}public void setPriceCode(int _priceCode) {switch(_priceCode){case REGULAR:_price = new RegularPrice();break;case NEW_RELEASE:_price = new NewReleasePrice();break;case CHILDRENS:_price = new ChildrensPrice();break;default:throw new IllegalArgumentException(" Incorrect PriceCode! ");}} ...

?

?

2.3.4 ?把租金計(jì)算方法移動(dòng)到 Price 類,在Movie 類中調(diào)用即可。

?

?

?

package bean;/*** 租金* @author Administrator*/ public abstract class Price {abstract int getPriceCode();/*** 計(jì)算租金* @param dayRented 租賃天數(shù)* @return*/double getCharge(int dayRented){double result = 0; // 租金// 確定每種片子的租金switch(getPriceCode()){case Movie.REGULAR:result += 2;if(dayRented > 2 ){result += (dayRented - 2) * 1.5;}break;case Movie.NEW_RELEASE:result += dayRented*3;break;case Movie.CHILDRENS:result += 1.5;if(dayRented > 3 ){result += (dayRented - 3) * 1.5;}break;}return result;} }

?

/*** 計(jì)算租金* @param dayRented 租賃天數(shù)* @return*/double getCharge(int dayRented){return _price.getCharge(dayRented); // 這是在 Movie 類中的調(diào)用}

?

?

2.3.5 ?重構(gòu)租金計(jì)算方法,把每個(gè)getCharge 方法中switch 的每個(gè) case 取出,在相應(yīng)的Price子類中寫一個(gè)覆蓋函數(shù)。

?

?

最后把Price的 租金計(jì)算方法改為抽象方法。

租金類 Price 重構(gòu)前:

?

package bean;/*** 租金* @author Administrator*/ public abstract class Price {abstract int getPriceCode();/*** 計(jì)算租金* @param dayRented 租賃天數(shù)* @return*/double getCharge(int dayRented){double result = 0; // 租金// 確定每種片子的租金switch(getPriceCode()){case Movie.REGULAR:result += 2;if(dayRented > 2 ){result += (dayRented - 2) * 1.5;}break;case Movie.NEW_RELEASE:result += dayRented*3;break;case Movie.CHILDRENS:result += 1.5;if(dayRented > 3 ){result += (dayRented - 3) * 1.5;}break;}return result;} }


? 重構(gòu)getCharge 方法后Price類 及子類 為:

?

?

package bean;/*** 租金* @author Administrator*/ public abstract class Price {abstract int getPriceCode();/*** 計(jì)算租金* @param dayRented 租賃天數(shù)* @return*/abstract double getCharge(int dayRented);}

?

package bean;/*** 兒童片租金* @author Administrator*/ public class ChildrensPrice extends Price {@Overrideint getPriceCode() {return Movie.CHILDRENS;}/*** 計(jì)算租金* @param dayRented 租賃天數(shù)* @return*/@Overridedouble getCharge(int dayRented){double result = 1.5;if(dayRented > 3){result += (dayRented - 3) * 1.5;}return result;} }

?

package bean; /*** 新片租金* @author Administrator*/ public class NewReleasePrice extends Price {@Overrideint getPriceCode() {return Movie.NEW_RELEASE;}/*** 計(jì)算租金* @param dayRented 租賃天數(shù)* @return*/@Overridedouble getCharge(int dayRented){return dayRented*3;}}

?

package bean;/*** 普通片租金* @author Administrator*/ public class RegularPrice extends Price {@Overrideint getPriceCode() {return Movie.REGULAR;}/*** 計(jì)算租金* @param dayRented 租賃天數(shù)* @return*/@Overridedouble getCharge(int dayRented){double result = 2;if(dayRented > 2){result += (dayRented - 2) * 1.5;}return result;} }

?

2.3.6 對積分計(jì)算方法作相同重構(gòu)。

從 Movie 類中移動(dòng)積分計(jì)算方法到 Price 類中。Movie 類中調(diào)用Proce的積分計(jì)算方法就行了。

?

package bean;/*** 租金* @author Administrator*/ public abstract class Price {abstract int getPriceCode();/*** 計(jì)算租金* @param dayRented 租賃天數(shù)* @return*/abstract double getCharge(int dayRented);/*** ??头e分計(jì)算* @param dayRented 租賃天數(shù)* @return*/int getFrequentRenterPoints(int dayRented){// (新片+租賃時(shí)間達(dá)2天 積分+1 )if(getPriceCode() == Movie.NEW_RELEASE && dayRented > 1){return 2;}else{return 1;}} }

?

package bean;/*** 影片* @author Administrator*/ public class Movie {public static final int CHILDRENS = 2; // 兒童片public static final int REGULAR = 0; // 普通片public static final int NEW_RELEASE = 1; // 新片private String _title;private Price _price; public Movie(String _title, int _priceCode) {this._title = _title;setPriceCode(_priceCode);}public int getPriceCode() {return _price.getPriceCode();}.../*** 常客積分計(jì)算* @param dayRented 租賃天數(shù)* @return*/int getFrequentRenterPoints(int dayRented){return _price.getFrequentRenterPoints(dayRented);}} .../*** 常客積分計(jì)算* @param dayRented 租賃天數(shù)* @return*/int getFrequentRenterPoints(int dayRented){return _price.getFrequentRenterPoints(dayRented);}}

?

?

對 Proce 類的積分計(jì)算方法重構(gòu),只是為新片類型增加一個(gè)覆寫函數(shù),并在超類中保留原函數(shù),使它成為一種默認(rèn)行為。

?

?

?

package bean;/*** 租金* @author Administrator*/ public abstract class Price {abstract int getPriceCode();.../*** 常客積分計(jì)算* @param dayRented 租賃天數(shù)* @return*/int getFrequentRenterPoints(int dayRented){// 默認(rèn)積1分return 1;} }

?

?

package bean; /*** 新片租金* @author Administrator*/ public class NewReleasePrice extends Price {.../*** 常客積分計(jì)算* @param dayRented 租賃天數(shù)* @return*/@Overrideint getFrequentRenterPoints(int dayRented){// (新片+租賃時(shí)間達(dá)2天 積分+1 )return (dayRented > 1) ? 2 : 1 ;} } .../*** ??头e分計(jì)算* @param dayRented 租賃天數(shù)* @return*/@Overrideint getFrequentRenterPoints(int dayRented){// (新片+租賃時(shí)間達(dá)2天 積分+1 )return (dayRented > 1) ? 2 : 1 ;} }

?

到此,重構(gòu)-改善既有代碼的設(shè)計(jì)-第1例:租賃影片,就重構(gòu)完成了。
總結(jié) :這樣重構(gòu)以后,不論是修改影片分類結(jié)構(gòu),還是修改租金計(jì)算規(guī)則又或積分計(jì)算規(guī)則就都容易多了 。

?

注:個(gè)人覺得 Movie 類中的?setPriceCode 方法 ?中得每種 price 的時(shí)候不該用構(gòu)造函數(shù),而是該直接調(diào)用各Price 子類 中的 getPriceCode 方法。

但此博文尊重原書中代碼未作改動(dòng)。

?

最后 所有類完整代碼為:

?

package bean;import java.util.Enumeration; import java.util.Vector;/*** 顧客* @author Administrator*/ public class Customer{private String _name; // 顧客名字private Vector _rentals = new Vector(); // 租賃訂單數(shù)組public Customer(String name) {super();this._name = name;}public void addRental(Rental arg){_rentals.addElement(arg);}public String getName() {return _name;}/*** 生成訂單(打印憑條)* @return*/public String htmlStatement(){Enumeration rentals = _rentals.elements();String result = "<P><H1>Rentals for <EM> "+ getName() + "</EM></H1></P>\n";while( rentals.hasMoreElements()){Rental each = (Rental)rentals.nextElement();// 本次租賃記錄說明result += each.getMovie().getTitle()+":"+ String.valueOf(each.getCharge())+"<BR>\n";}// 頁腳result +="<P>You owe <EM>"+ String.valueOf(getTotalCharge())+"</EM></P>\n";result +="<P> on this rental you earned <EM> "+String.valueOf(getTotalFrequentRenterPoints())+"</EM> frequent renter points </P>";return result;}// 計(jì)算總積分private int getTotalFrequentRenterPoints(){int result = 0;Enumeration rentals = _rentals.elements();while(rentals.hasMoreElements()){Rental each = (Rental)rentals.nextElement();result += each.getFrequentRenterPoints();}return result;}// 計(jì)算總租金private double getTotalCharge(){double result = 0;Enumeration rentals = _rentals.elements();while(rentals.hasMoreElements()){Rental each = (Rental)rentals.nextElement();result += each.getCharge();}return result;}}

?

?

package bean; /*** 租賃訂單* @author Administrator*/ public class Rental {private Movie _movie ; // 影片private int _daysRented; // 租賃天數(shù)public Rental(Movie _movie, int _daysRented) {this._movie = _movie;this._daysRented = _daysRented;}public Movie getMovie() {return _movie;}public int getDaysRented() {return _daysRented;}/*** ??头e分計(jì)算* @return*/int getFrequentRenterPoints(){return _movie.getFrequentRenterPoints(_daysRented);}/*** 計(jì)算租金* @return*/double getCharge(){return _movie.getCharge(_daysRented);}}

?

package bean;/*** 影片* @author Administrator*/ public class Movie {public static final int CHILDRENS = 2; // 兒童片public static final int REGULAR = 0; // 普通片public static final int NEW_RELEASE = 1; // 新片private String _title;private Price _price; public Movie(String _title, int _priceCode) {this._title = _title;setPriceCode(_priceCode);}public int getPriceCode() {return _price.getPriceCode();}public void setPriceCode(int _priceCode) {switch(_priceCode){case REGULAR:_price = new RegularPrice();break;case NEW_RELEASE:_price = new NewReleasePrice();break;case CHILDRENS:_price = new ChildrensPrice();break;default:throw new IllegalArgumentException(" Incorrect PriceCode! ");}}public String getTitle() {return _title;}/*** 計(jì)算租金* @param dayRented 租賃天數(shù)* @return*/double getCharge(int dayRented){return _price.getCharge(dayRented);}/*** 常客積分計(jì)算* @param dayRented 租賃天數(shù)* @return*/int getFrequentRenterPoints(int dayRented){return _price.getFrequentRenterPoints(dayRented);}}

?

package bean;/*** 租金+積分* @author Administrator*/ public abstract class Price {abstract int getPriceCode();/*** 計(jì)算租金* @param dayRented 租賃天數(shù)* @return*/abstract double getCharge(int dayRented);/*** 常客積分計(jì)算* @param dayRented 租賃天數(shù)* @return*/int getFrequentRenterPoints(int dayRented){// 默認(rèn)積1分return 1;} }

?

package bean;/*** 兒童片租金* @author Administrator*/ public class ChildrensPrice extends Price {@Overrideint getPriceCode() {return Movie.CHILDRENS;}/*** 計(jì)算租金* @param dayRented 租賃天數(shù)* @return*/@Overridedouble getCharge(int dayRented){double result = 1.5;if(dayRented > 3){result += (dayRented - 3) * 1.5;}return result;} }

?

package bean; /*** 新片租金* @author Administrator*/ public class NewReleasePrice extends Price {@Overrideint getPriceCode() {return Movie.NEW_RELEASE;}/*** 計(jì)算租金* @param dayRented 租賃天數(shù)* @return*/@Overridedouble getCharge(int dayRented){return dayRented*3;}/*** 常客積分計(jì)算* @param dayRented 租賃天數(shù)* @return*/@Overrideint getFrequentRenterPoints(int dayRented){// (新片+租賃時(shí)間達(dá)2天 積分+1 )return (dayRented > 1) ? 2 : 1 ;} } package bean;/*** 普通片租金* @author Administrator*/ public class RegularPrice extends Price {@Overrideint getPriceCode() {return Movie.REGULAR;}/*** 計(jì)算租金* @param dayRented 租賃天數(shù)* @return*/@Overridedouble getCharge(int dayRented){double result = 2;if(dayRented > 2){result += (dayRented - 2) * 1.5;}return result;} }

?

?

?

?

?

?

?

?

?

總結(jié)

以上是生活随笔為你收集整理的《重构-改善既有代码的设计》-第1例:租赁影片(2)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。