Java - getter/setter,行为和接口



我有一个问题,有点理论性:

假设,我有以下类:

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。除了把它放到构造函数中(我想把它变成一个春豆),处理这种情况的最佳实践是什么?

假设您可以更改界面,以下是我能想到的一些解决方案:

解决方案#1

void execute(Optional<String> release);

void execute(@Nullable String release);

然后将它们用作execute(Optional.empty())execute(null)Report类。

解决方案#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,这样您的实现类就不必担心实现不受支持的方法。


使用最适合您的可读性和可维护性。

解决方案 1:弹簧依赖注入 - 字段注入:

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
}
}

我将"字符串发布"更改为"发布发布",因为制作"字符串"的豆子也很奇怪。因此,"发布"类必须包含您的"字符串发布"。

如果"字符串发布"仅包含一些配置的值,则在运行时不会更改。然后,可以使用 @Value 从属性文件中读取其字符串值。

解决方案 2:弹簧构造函数注入:

构造函数注入是另一种选择,更推荐。 然后,您的报告 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();

相关内容

  • 没有找到相关文章

最新更新