Switch語句這個壞味道僚祷,到底壞在哪里?

在老馬的《重構》第1版中遂赠,將Switch Statement定義成一個代碼壞味道。而且里面提到一句:

大多數(shù)時候晌杰,一看到Switch語句跷睦,你就應該考慮以多態(tài)替換它。

我最初看到這個描述的時候肋演,我持有一點疑慮的抑诸。你仔細想,如果Switch Statement是一個壞味道的話爹殊,那程序中的條件分支(if-else)也是一種壞味道蜕乡,因為if-else和switch從本質(zhì)上都是條件分支。然而梗夸,if-else沒有被公認為一種代碼壞味道层玲,而且在程序中不可避免會用到這個。

在《重構》第2版中反症,老馬直接將這個壞味道改成 Repeated Switches辛块,并做了澄清:

因為在20世紀90年代末,程序員太過于忽視多態(tài)的價值铅碍,我們希望矯枉過正润绵。如今的程序員已經(jīng)更多地使用多態(tài),switch語句也不像15年前那樣有害無益胞谈,很多語言支持更復雜的switch語句尘盼,而不只是根據(jù)基本類型值來做判斷條件憨愉。因此。我們現(xiàn)在更關注重復的Switch

實際上**重復才是罪魁禍首卿捎,重復會讓代碼修改起來更加困難配紫。在第一版中,他其實也提到這點:

從本質(zhì)上講娇澎,switch語句的問題在于重復笨蚁,你會經(jīng)常發(fā)現(xiàn)同樣的switch語句散布在不同的地方。如果為它添加一個新的case字句趟庄,就必須找到所有switch語句并修改它們括细。

作為重構的初學者,當你看到wwitch壞味道的時候戚啥,要抓住重復這個關鍵點奋单,而且重復的switch有可能以if-else體現(xiàn)出來。只要有相同的條件判斷值在多處出現(xiàn)猫十,就散發(fā)出Repeated Switch的味道览濒。沒必要的重復的代碼,是你應該要提高警惕的地方拖云,接下來可能要想點辦法消除它贷笛,比如使用多態(tài)來取代。

這里附上一個重復Switch的案例:

案例一:

public class Item {

    private String name;

    private int sellIn;

    private int quality;

    public Item(String name, int sellIn, int quality) {
        this.name = name;
        this.sellIn = sellIn;
        this.quality = quality;
    }

    @Override
    public String toString() {
        return this.name + ", " + this.sellIn + ", " + this.quality;
    }

    void update() {
        updateQuality();

        updateSellIn();

        if (isExpired()) {
            updateQualityAfterExpired();
        }
    }

    private boolean isExpired() {
        return sellIn < 0;
    }

    private void updateQuality() {
        if (isAgedBrie()) {
            if (quality < 50) {
                quality = quality + 1;
            }
            return;
        }
        if (isBackstagePass()) {
            increaseQuality();
            if (sellIn < 11) {
                increaseQuality();
            }
            if (sellIn < 6) {
                increaseQuality();
            }
            return;
        }
        if (isSulfuras()) {
            return;
        }
        if (quality > 0) {
            quality = quality - 1;
        }
    }

    private void updateSellIn() {
        if (isSulfuras()) {
            return;
        }
        sellIn = sellIn - 1;
    }

    private void updateQualityAfterExpired() {
        if (isAgedBrie()) {
            increaseQuality();
            return;
        }
        if (isBackstagePass()) {
            quality = 0;
            return;
        }
        if (isSulfuras()) {
            return;
        }
        if (quality > 0) {
            quality = quality - 1;
        }
    }

    private void increaseQuality() {
        if (quality < 50) {
            quality = quality + 1;
        }
    }

    private boolean isSulfuras() {
        return name.equals("Sulfuras, Hand of Ragnaros");
    }

    private boolean isBackstagePass() {
        return name.equals("Backstage passes to a TAFKAL80ETC concert");
    }

    private boolean isAgedBrie() {
        return name.equals("Aged Brie");
    }
}

案例二:

public class CheckInSystem {
    private Map<String, String> checkInRecords = new HashMap<>();

    public  boolean checkIn(String fingerprint){
        Employee employee = EmployeeRepository.query(fingerprint);
        int type = employee.getType();
        String record;
        switch (type) {
            case Employee.ENGINEER:
                record = "I am an Engineer, My Name is" + employee.getName();
                break;
            case Employee.SALESMAN:
                record = "I am a Salesman, My Name is" + employee.getName();
                break;
            case Employee.MANAGER:
                record = "I am a Manager, My Name is" + employee.getName();
                break;
            default:
                record = "";
        }
        if (checkInRecords.isEmpty()) {
            return false;
        }
        checkInRecords.put(fingerprint, record);

        return true;
    }
}

public class Employee {
    static final int ENGINEER = 0;
    static final int SALESMAN = 1;
    static final int MANAGER = 2;

    private int type;
    private String name;
    private int monthlySalary;
    private int commission;
    private int bonus;

    public Employee(int type) {
        this.type = type;
    }

    public int getType() {
        return type;
    }

    public String getName() {
        return name;
    }

    public int payAmount() {
        switch (type) {
            case ENGINEER:
                return monthlySalary;
            case SALESMAN:
                return monthlySalary + commission;
            case MANAGER:
                return monthlySalary + bonus;
            default:
                throw new RuntimeException("Invalid employee");
        }
    }
}

以上代碼宙项,你找到了重復的Switch了嗎乏苦?

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市尤筐,隨后出現(xiàn)的幾起案子汇荐,更是在濱河造成了極大的恐慌,老刑警劉巖盆繁,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件掀淘,死亡現(xiàn)場離奇詭異,居然都是意外死亡油昂,警方通過查閱死者的電腦和手機革娄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來冕碟,“玉大人稠腊,你說我怎么就攤上這事∶В” “怎么了架忌?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長我衬。 經(jīng)常有香客問我叹放,道長饰恕,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任井仰,我火速辦了婚禮埋嵌,結果婚禮上,老公的妹妹穿的比我還像新娘俱恶。我一直安慰自己雹嗦,他們只是感情好,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布合是。 她就那樣靜靜地躺著了罪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪聪全。 梳的紋絲不亂的頭發(fā)上泊藕,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天,我揣著相機與錄音难礼,去河邊找鬼楚午。 笑死妄迁,一個胖子當著我的面吹牛重挑,可吹牛的內(nèi)容都是我干的姑躲。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼谦炬,長吁一口氣:“原來是場噩夢啊……” “哼悦屏!你這毒婦竟也來了?” 一聲冷哼從身側響起吧寺,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤窜管,失蹤者是張志新(化名)和其女友劉穎散劫,沒想到半個月后稚机,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡获搏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年赖条,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片常熙。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡纬乍,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出裸卫,到底是詐尸還是另有隱情仿贬,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布墓贿,位于F島的核電站茧泪,受9級特大地震影響蜓氨,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜队伟,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一穴吹、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧嗜侮,春花似錦港令、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至宜猜,卻和暖如春泼返,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背姨拥。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工绅喉, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人叫乌。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓柴罐,卻偏偏與公主長得像,于是被迫代替她去往敵國和親憨奸。 傳聞我的和親對象是個殘疾皇子革屠,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355