java策略枚舉

 我們在使用Java的枚舉時往往會結合Switch來進行判斷以實現不同值的處理,但是我們知道多用switch不是一種很好的代碼風格,不利用維護和適應變化,因爲這不符合開-閉原則。爲此一種方法是用策略模式來重構原有的枚舉實現,但是很多時候確實需要用枚舉的方法來實現,如一週的天數等等,這也是JDK5.0重新引入枚舉的原因。Joshua Bloch在Effective Java(第二版)裏提出了一種枚舉策略模式 很好的解決了這個問題。

    要說明問題最好的辦法就是結合例子,比如我們要定義一年的12個月,往往會想到枚舉,假設我們要定義一個返回某年某個月的天數的方法,我們知道一個月一般是30,31天,其中2月比較特殊,閏年是28天,其他年份是29天,如果單純用swtich的話顯然不是一種很好的代碼風格,這個例子還好,因爲我們知道一年12月不會變,但有的枚舉可能在今後添加新的類型,這樣我們就不得不去修改原有的switch了,明顯不符合開--閉原則,影響維護並且容易引入Bug。

    這時我們可以利用嵌套枚舉和接口結合的方法來實現開閉原則的思想。



 public enum Year {
	JAN(MonType.BIG), FEB(MonType.SPECIAL), MAR(MonType.BIG), APR(MonType.SMALL), MAY(
			MonType.BIG), JUN(MonType.SMALL),//剩餘月份略掉;
	Year(MonType type) {
		this.type = type;
	}
	private final MonType type;
    public int ContainDays(int year) {
       return type.countResult(year);
	}
	private enum MonType implements Count {
		BIG {
			public int countResult(int num) {
				return 31;
			}
		},
		SMALL {
			public int countResult(int num) {
				return 30;
			}
		},
		SPECIAL {
			public int countResult(int num) {
				if ((num % 4 == 0 && num % 100 != 0) || (num % 400 == 0)) {
                       return 28;
				} else {
					return 29;
				}				
			}
		}
	}
}

    
  public interface Count {
	public int countResult(int num);
}

在上面這段代碼裏Year枚舉的ContainDays方法返回某年某月的天數,因爲大月,小月,閏年和非閏年的2月返回的天數都是不一樣的,也就是根據輸入參數計算的策略可能不一樣,這種情況下我們應抽象出接口來適應這種變化,但是要是直接在Year枚舉裏12月的類型實例一一實現該接口就會帶來很多重複代碼(代碼有臭味了),因爲像1,3,5等都是返回31天的,也就是計算方法一樣,而如用嵌套枚舉(相當於內部類),外層枚舉把處理方法委託給了內部枚舉,讓內部枚舉(代表每個月計算天數的不同類型)來具體實現Count接口(用來返回每月天數),則很好的消除了冗餘代碼,並且今後要是添加其他處理類型,只需再次實現Count接口,原有的代碼無需改變,很好的實現了開閉原則。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章