簡體   English   中英

使用setter將服務注入Enum ......糟糕的做法?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM