[英]using setter to inject service into Enum…Bad Practice?
這被認為是不好的做法嗎? 本質上,基於枚舉我想在接口中調用特定方法。 每個枚舉都有自己的接口實現(WalkImpl,RunImpl,JogIMpl等),所有這些都基於ActivityService接口。 我只是想知道這是將服務“注入”Enum的正確方法。 我這樣做是因為我無法自動提供服務。 謝謝
@Component
public class HelloWorldImpl implements HelloWorld {
private enum MyEnum{
WALK {
@Override
public void execute() {
System.out.println("I am walking");
activityService.doSomethingWithMe(this.name());
}
},
RUN{
@Override
public void execute() {
System.out.println("I am running");
}
},JOG{
@Override
public void execute() {
System.out.println("I am jogging!");
}
}, SKIP{
@Override
public void execute() {
System.out.println("I am skipping!");
}
};
public abstract void execute();
private static ActivityService activityService;
public void setActivityService(ActivityService activityService) {
this.activityService = activityService;
}
}
@Autowired
ActivityService activityService;
@Override
public void executeMe(){
MyEnum myEnum = MyEnum.WALK;
myEnum.setActivityService(activityService);
myEnum.execute();
}
}
不要使用這樣的枚舉。 當我有更多的時間我將解釋,但大多數程序員期望甚至Java語言有點期望枚舉是冪等的和不可變的。
枚舉中的所有成員變量都應該是final,枚舉不應該產生副作用。 這是因為枚舉是函數式編程風格調度的一種形式(盡管很糟糕)。 這應該被視為符號而不是對象(即使它們是單例對象)。
除非您遵循上面的功能規則,否則不要使用枚舉來解決單例模式。 以下是我可能會對您的代碼進行修改:
@Component
public class HelloWorldImpl implements HelloWorld {
private enum MyEnum{
//Notice the final here
private final String message;
WALK ("I am walking"),
RUN("I am running"),
JOG("I am jogging!"),
SKIP("I am skipping!");
public MyEnum(String message) { this.message = message; }
public String getMessage() { return this.message; }
}
@Autowired
ActivityService activityService;
@Override
public void executeMe() {
MyEnum myEnum = MyEnum.WALK;
_executeMe(myEnum);
}
void _executeMe(MyEnum m) {
//switch or if on the enums you want to
//do stuff on with the activity service.
System.out.println(m.getMessage());
if (m == MyEnum.WALK)
activityService.doSomethingWithMe(m.name());
}
}
枚舉最適合用於必須在代碼中區分的事物 - 業務邏輯。 如果您將它們用於數據(作為示例),對我來說沒有任何意義。
此外,通過數據與代碼我不是簡單地迭代它們,你實際上必須使用不同的枚舉使用明顯不同的代碼,否則它們只是一個(壞的)數據初始化設備。
更好地初始化該類型的數據可能是:
String[] init=new String[] {"WALK", "I am walking", "SKIP", "I am skipping", ...}
Map lookup=new HashMap();
for(int i=0;i+=2;i<init.length)
{
lookup.put(init[i],init[i+1])
}
沒有冗余,簡單得多,當列表變得更復雜時,將它放在代碼之外的文本,屬性,xml或您喜歡的任何數據風格都是微不足道的。
你甚至可以通過將“查找”和整個初始化包裝到一個對象中來將代碼與這些代碼相關聯(這是一個好主意)我會做出如下所示的內容:
public class Motivate()
{
private static Map<String, Motivate> motivations;
private String action;
private String description;
private Motivate(String action, String description)
{
this.action=action;
this.description=description;
}
public void init()
{
if(motivations == null)
{
build motivations using all the stuff in the first example
}
}
}
如果你想要附加不同的代碼(假設你的例子很簡單,每個“模式”需要不同的代碼),添加一個包含“Runnable”之類的接口的成員,並在構建它時將其傳遞給構造函數。
那么你的代碼永遠不應該引用“RUN”或“WALK”,它只是綁定到例如用戶擊鍵或其他數據的數據。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.