[英]Java - Getter/Setter, behavior and Interfaces
我有一個問題,有點理論:
假設,我有以下課程:
interface ReportInterface {
void execute();
}
class Report implements ReportInterface {
private final Repository rep;
Report(Repository ref){
this.rep = ref;
}
public void execute(){
//do some logic
}
}
class ReportWithSetter implements ReportInterface {
private final Repository rep;
private String release;
ReportWithSetter(Repository ref){
rep = ref;
}
public void execute(){
if (release == null) throw IlligalArgumentException("release is not specified");
//do some logic
}
public void setRelease(String release){
this.release=release;
}
}
第二個報告需要一個額外的參數釋放才能正常工作,但我的接口定義為沒有execute
方法的參數,所以我用一個 setter 方法解決它,所以它看起來像:
ReportWithSetter rep2 = new ReportWithSetter (rep);
rep.setRelease("R1.1");
rep.execute();
所以我不喜歡這個額外的rep.setRelease
。 我看起來很奇怪和做作 - 這個類的用戶可能會感到困惑,例如,如果我在 Spring 中將該類作為單例 bean,它是潛在錯誤的來源,如果它被第二次請求而有人忘記了第二次觸發rep.setRelease
。 除了將它放入構造函數(我想將它變成一個 spring bean)之外,處理這種情況的最佳做法是什么?
假設您可以更改界面,這里有一些我能想到的解決方案:
解決方案#1
void execute(Optional<String> release);
或者
void execute(@Nullable String release);
然后將它們用於Report
類作為execute(Optional.empty())
或execute(null)
。
解決方案#2
void execute(String... release);
然后將其用於Report
類作為execute()
並將其用於ReportWithSetter
類作為execute("R1.1")
。
解決方案#3
定義兩個void execute();
和void execute(String release);
在界面中。 然后在實現時,在不需要的方法中拋出UnsupportedOperationException
。 例如,在Report
類中,您將執行以下操作:
public void execute(){
//do some logic
}
public void execute(String release){
throw new UnsupportedOperationException("Use the overloaded method");
}
您還可以將這兩個方法設為接口中的default
方法,這樣您的實現類就不必擔心實現不受支持的方法。
使用對您來說最易讀和最易於維護的那個。
方案一:Spring依賴注入——字段注入:
Spring 的依賴注入與反射一起工作,因此不需要 Setter 方法。
因此,如果您將 Report 類設為 Spring Bean 並使用 @Autowired 注入另一個 bean,則不需要 Setter 方法。
它看起來像這樣:
@Component
class ReportWithRelease implements ReportInterface {
@Autowired private final Repository rep;
@Autowired private Release release;
public void execute(){
if (release == null) throw IlligalArgumentException("release is not specified");
//do some logic
}
}
我把“String release”改成了“Release release”,因為做一個“String”的bean也會很奇怪。 所以“Release”類必須包含你的“String release”。
如果“String release”只包含一些配置值,在運行時不會改變。 然后您可以使用@Value 從屬性文件中讀取其字符串值。
解決方案2:Spring構造函數注入:
構造函數注入是另一種選擇,更值得推薦。 那么您的 Report bean 將如下所示:
@Component
class ReportWithRelease implements ReportInterface {
private Repository rep;
private Release release;
@Autowired
public ReportWithRelease(Repository rep, Release release) {
this.rep = rep;
this.release = release;
}
public void execute(){
if (release == null) throw IlligalArgumentException("release is not specified");
//do some logic
}
}
如果你想創建相同接口的不同類的實例,工廠方法模式是很好的。
class MyFactory {
ReportInterface createInstance(Class clazz, String... args) {
if (Report.class.equals(clazz)) {
return new Report();
}
if (ReportWithSetter.class.equals(clazz)) {
return new ReportWithSetter(args[0]);
}
throw new IllegalArgumentException(clazz.getName());
}
}
Spring當然提供自動裝配,但是為了系統目的應該引入@AutoWire。
在這里,您可以使用兩階段執行,即工廠。
class ReportFactory /*ReportWithSetter*/ {
private final Repository rep;
private final String release;
private final ReportInterface report = ...;
ReportFactory (Repository rep, String release) {
this.rep = rep;
this.release = release;
}
public ReportInterface report() {
return report;
}
}
new ReportFactory(rep, release).execute();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.