js 使用多态替换条件语句_用多态和组成替换多个条件
js 使用多態(tài)替換條件語(yǔ)句
用多態(tài)替換條件語(yǔ)句是一種眾所周知的重構(gòu)模式。 如果您不熟悉該模式,可以在此處查看 。 但是,一旦類(lèi)中有多個(gè)條件檢查所基于的字段,該基本解決方案便會(huì)開(kāi)始崩潰。 我們將研究一些有關(guān)如何使用這些可能性的想法。
有很多方法可以解決,因此我們將從最簡(jiǎn)單到最困難的工作,始終使用簡(jiǎn)單的示例來(lái)盡可能減少混亂。 那么,最簡(jiǎn)??單的情況是什么? 看一看:
public class ClassWithConditionals {private boolean conditional1;private EnumeratedType conditional2;public ClassWithConditionals(boolean cond1, EnumeratedType cond2){conditional1 = cond1;conditional2 = cond2;}public void method1(){if(conditional1){//do something}else{//do something else}}public void method2(){switch(conditional2){case CASE1://do somethingbreak;case CASE2://do something elsebreak;case CASE3://do something entirely differentbreak;}} }enum EnumeratedType {CASE1,CASE2,CASE3 }因此,在此示例中,我們有ClassWithConditionals在其方法中使用的兩個(gè)不同字段。 在一個(gè)合適的示例中,您將假設(shè)使用的方法不只是給定的兩個(gè),但在示例中我們只需要兩個(gè)。 如果每種條件只使用一種方法,則無(wú)需擔(dān)心,因?yàn)榫S護(hù)成本仍然很低。 但是,只要執(zhí)行這種條件檢查的方法數(shù)量增加,就應(yīng)該考慮進(jìn)行這種重構(gòu)。
通常,如果您要遵循用多態(tài)替換條件,您將最終得到六個(gè)類(lèi)來(lái)解決此問(wèn)題: boolean和enum每種組合都需要一個(gè)。 取而代之的是,我們將使用合成。
那么,第一步是什么? 首先,我們可能應(yīng)該使用enum類(lèi)型。 enum可以有自己的方法,可以以允許其根據(jù)特定enum做不同事情的方式定義這些方法。 因此,讓我們將enum eratedType更改為如下形式:
enum EnumeratedType {CASE1(){public void doSomething(){//do something}},CASE2(){public void doSomething(){//do something else}},CASE3(){public void doSomething(){//do something entirely different}};public abstract void doSomething(); }現(xiàn)在, method2僅需要將自身委托給conditional2.doSomething() 。
現(xiàn)在讓我們修復(fù)boolean 。 我們創(chuàng)建一個(gè)接口,該接口對(duì)所有非封裝類(lèi)(為進(jìn)行測(cè)試,可能還有該包)都私有,稱(chēng)為Conditional1 。 然后我們用True和False對(duì)其進(jìn)行子類(lèi)化。 這是代碼:
interface Conditional1 {static Conditional1 TRUE = new True();static Conditional1 FALSE = new False();void doSomething(); }class True implements Conditional1 {public void doSomething(){//do something} }class False implements Conditional1 {public void doSomething(){//do something else} }我決定在接口上創(chuàng)建TRUE和FALSE實(shí)例的原因很簡(jiǎn)單:它們都是無(wú)狀態(tài)類(lèi),這意味著每個(gè)實(shí)例都具有多個(gè)實(shí)例是沒(méi)有意義的。 它還允許我們像enum一樣調(diào)用它們。
同樣,現(xiàn)在主要類(lèi)只需要委托。 這是固定類(lèi)現(xiàn)在的樣子
public class ClassWithConditionals {public static ClassWithConditionals with(boolean cond1, EnumeratedType cond2){Conditional1 conditional1;if(cond1)conditional1 = Conditional1.TRUE;elseconditional1 = Conditional1.FALSE;return new ClassWithConditionals(conditional1, cond2);}private Conditional1 conditional1;private EnumeratedType conditional2;ClassWithConditionals(Conditional1 cond1, EnumeratedType cond2){this.conditional1 = cond1;this.conditional2 = cond2;}public void method1(){conditional1.doSomething();}public void method2(){conditional2.doSomething();} }這里有些奇怪。 我們已經(jīng)用另一個(gè)替換了一個(gè)條件。 我們的構(gòu)造函數(shù)足以接受一個(gè)Conditional1 ,但是我們有一個(gè)靜態(tài)工廠方法,該方法仍然采用boolean并對(duì)此進(jìn)行條件檢查。
考慮到從技術(shù)上講,除非有多種方法在進(jìn)行檢查,否則我們不會(huì)重構(gòu)此代碼,因此,我們進(jìn)行了許多檢查并將其歸為一類(lèi)。 同樣,在工廠中通常認(rèn)為有條件的還可以,將所有檢查都強(qiáng)制在一個(gè)地方,并允許多態(tài)性從那里接管。 您不必使用靜態(tài)工廠方法作為工廠,但是它是最快速,最簡(jiǎn)單的即時(shí)設(shè)置方法。 允許調(diào)用新ClassWithConditionals對(duì)象的創(chuàng)建代碼的代碼仍然可以按過(guò)去的方式傳遞boolean的另一個(gè)好處是,它允許我們封裝和隱藏基于條件的類(lèi)的實(shí)現(xiàn)細(xì)節(jié)。 新ClassWithConditionals創(chuàng)建者無(wú)需擔(dān)心創(chuàng)建Conditional1對(duì)象,甚至無(wú)需知道它的存在。
我們?nèi)匀幌M麡?gòu)造函數(shù)接受Conditional1對(duì)象,這有兩個(gè)原因:1)它將條件邏??輯保存在工廠中,而不是構(gòu)造函數(shù)中,后者是首選,并且2)它允許我們傳遞Conditional1對(duì)象的測(cè)試雙精度。
實(shí)際上,由于第2點(diǎn),我們應(yīng)該經(jīng)常考慮將enum轉(zhuǎn)換為更類(lèi)似于Conditional1的靜態(tài)實(shí)例。 這將允許您更多地使用測(cè)試雙打。 它還將有助于繼承或通過(guò)合成進(jìn)行擴(kuò)展,這將在稍后進(jìn)行討論。
可以想到很多小變化。 首先,條件boolean不需要boolean或enum 。 可以有一組基于數(shù)字或其他條件的條件表達(dá)式。 通常,在這些情況下,我們用小的幫助程序方法替換支票以使其更清晰,即if(numberOfPeople <= 3)...變成if(isACrowd(numberOfPeople))... 我們可以更進(jìn)一步,并創(chuàng)建通過(guò)工廠創(chuàng)建的GroupsOfPeople層次結(jié)構(gòu)。 如果工廠的值為1,則返回SinglePerson ; 給定2,則返回Company對(duì)象; 給定3或更多,它將返回Crowd對(duì)象。 這些對(duì)象中的每個(gè)對(duì)象都有其自己的方法,這樣可以幫助減少原始類(lèi)中的代碼量。
另一個(gè)變化是當(dāng)不同的條件字段集分層在一起時(shí)( if(condition1 && condition2)等)。 為了解決這個(gè)問(wèn)題,您可以走繼承路線并創(chuàng)建爆炸式的類(lèi)以覆蓋所有組合。 另一種選擇是用較小的層次結(jié)構(gòu)替換一個(gè)條件對(duì)象,該層次結(jié)構(gòu)接受委托方法中的其他條件對(duì)象,在那里它仍然具有一些條件代碼,但是可讀性更強(qiáng)。 例如,您可以將使用兩個(gè)布爾值的類(lèi)轉(zhuǎn)換為如下形式:
public class ClassWithConditionals {public static ClassWithConditionals with(boolean condition1, boolean condition2){Conditional1 cond1;if(condition1)cond1 = Conditional1.TRUE;elsecond1 = Conditional1.FALSE;return new ClassWithConditionals(cond1, condition2);}private Conditional1 condition1;private boolean condition2;ClassWithConditionals(Conditional1 condition1, boolean condition2){this.condition1 = condition1;this.condition2 = condition2;}public void method(){condition1.method(condition2);} }interface Conditional1 {static Conditional1 TRUE = new True();static Conditional1 FALSE = new False();void method(boolean condition2); }class True implements Conditional1 {public void method(boolean condition2){if(condition2){//do something}else{//do something else}} }class False implements Conditional1 {public void method(boolean condition2){if(!condition2){//do something really different}//and do this} }Condition1的method接受一個(gè)布爾值,然后使用它進(jìn)行更多的條件處理。
此外,如果全部邏輯允許,您可以創(chuàng)建一組類(lèi)來(lái)替換其中一個(gè)條件,然后讓其創(chuàng)建代碼接受其他條件,以便確定其一部分創(chuàng)建。 例如:
public class ClassWithConditionals {public static ClassWithConditionals from(boolean condition1, boolean condition2){return new ClassWithConditionals(Conditional1.from(condition1, condition2));}private Conditional1 conditionOne;ClassWithConditionals(Conditional1 conditionOne){this.conditionOne = conditionOne;}public int method(){return conditionOne.method() * -6;} }interface Conditional1 {static Conditional1 from(boolean condition1, boolean condition2){if(condition1)return True.with(condition2);elsereturn False.with(condition2);}int method(); }class True implements Conditional1 {public static True with(boolean condition2){if(condition2)return new True(5);elsereturn new True(13);}private int secondary;public True(int secondary){this.secondary = secondary;}public int method(){return 2 * secondary;} }class False implements Conditional1 {public static False with(boolean condition2){if(condition2)return new False((x, y) -> x - y, 31);elsereturn new False((x, y) -> x * y, 61);}private final BinaryOperator operation;private final int secondary;public False(BinaryOperator operation, int secondary){this.operation = operation;this.secondary = secondary;}public int method(){return operation.apply(4, secondary);} }對(duì)于True ,第二個(gè)條件決定method計(jì)算中的次要數(shù)字。 在False ,它會(huì)執(zhí)行此操作并找出要應(yīng)用于計(jì)算的運(yùn)算符。
我不確定是否會(huì)發(fā)生類(lèi)似的事情,但是如果確實(shí)發(fā)生了,您現(xiàn)在知道了一種解決方法。
總的來(lái)說(shuō),這整套重構(gòu)實(shí)質(zhì)上將代碼從單個(gè)類(lèi)更改為Facade。 它需要大量的新類(lèi),并且使您可以使用與以前的單個(gè)類(lèi)幾乎完全相同的方式來(lái)使用整個(gè)工具包和kaboodle,唯一真正的區(qū)別是調(diào)用靜態(tài)工廠方法而不是構(gòu)造函數(shù)。
這不是特別重要; 我只是想向您指出。
希望您不必?fù)?dān)心繼承或“通過(guò)合成擴(kuò)展”此類(lèi)。 但是您可能必須這樣做。
如果您要編寫(xiě)的擴(kuò)展僅真正改變了條件對(duì)象的功能,則可以簡(jiǎn)單地編寫(xiě)一個(gè)新的Factory,為構(gòu)造函數(shù)提供一組新的條件對(duì)象。 例如,您可以將此靜態(tài)工廠方法添加到ClassWithConditionals的最新版本中:
public static ClassWithConditionals different(int value) {return new ClassWithConditionals(new SimpleConditional1(value)); }與SimpleConditional1看起來(lái)像這樣
class SimpleConditional1 implements Conditional1 {private final int value;public SimpleConditional1(int value){this.value = value;}public int method(){return value;} }除此之外,您還可以提供原始需要的任何條件對(duì)象,并覆蓋您需要覆蓋的所有方法。
因此,這就是我用更多的OO選項(xiàng)替換多個(gè)條件的結(jié)果。 您還有其他方法可以做到嗎? 您是否有一個(gè)無(wú)法奏效的示例,您想讓我大驚小怪? 讓我知道,我會(huì)解決。
謝謝閱讀。
翻譯自: https://www.javacodegeeks.com/2015/01/replacing-multiple-conditionals-with-polymorphism-and-composition.html
js 使用多態(tài)替換條件語(yǔ)句
總結(jié)
以上是生活随笔為你收集整理的js 使用多态替换条件语句_用多态和组成替换多个条件的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: unix系统 联想7605D驱动安装(u
- 下一篇: jboss默认进程名称_快速指南:剖析J