Java 中从客户端应用程序隐藏 public setter 的最佳方法
Best way in Java to hide public setters from client applications
我有一个构建在 DynamoDB 之上的 Spring 应用程序。我正在尝试编写一个 saveFoo()
存储库方法,它将 Foo
类型的对象保存到数据库中。该方法将从应用层调用。
我正在努力解决的问题是 Foo
class 中包含特定于 Dynamo 的字段。我不希望 saveFoo()
class 的客户认为他们需要使用这些字段创建类型为 Foo
的对象。我也不希望他们尝试自己设置这些值。
这些特定于数据库的字段需要 public getter 和 setter 才能与 DynamoDB SDK 一起使用。
数据库模型 class 如下所示:
@DynamoDBTable(tableName = "foo")
public class Foo {
// Fields the client should be setting
private String bar;
private String baz;
// Fields the client should not access and should not care about. They are internal fields used for DynamoDB purposes.
private Long version;
private String gsiIndexKey;
// Empty constructor needed for deserialization of data from dynamodb
public Foo() {
}
// Getters and setters for all of the above fields.
}
以及将对象保存到数据库的存储库方法:
public class FooRepositoryImpl {
public Foo saveFoo(WhatClassShouldThisBe foo) {
// Code that saves a new Foo item to the database and returns it.
}
}
我目前的想法是创建一个 FooWrapper 接口,saveFoo()
方法可以将其作为参数。包装器将允许客户端设置他们应该控制的字段,但不会公开与数据库内部相关的字段。类似下面的内容:
/**
* Allows us restrict visibility of the Foo fields to the Application by hiding database internal fields.
**/
public interface FooWrapper {
Foo getFoo()
}
public class FooWrapperImpl implements FooWrapper {
private final Foo foo;
public FooWrapperImpl(String bar, String baz) {
foo = new Foo();
foo.setBar(bar);
foo.setBaz(baz);
}
@Override
public Foo getFoo() {
return foo;
}
}
public class FooRepositoryImpl {
public Foo saveFoo(FooWrapper fooWrapper) {
Foo foo = fooWrapper.getFoo(); // Save this item to db
// Code that saves a new Foo item to the database and returns it.
}
}
您对这种方法有何看法?有谁知道我可以尝试一些更好的技术?我不禁觉得我在这里过度设计了东西。
仅向具有所需方法的客户端公开一个接口。在内部您可以调用实现的其他 public 方法,但客户端代码不会知道它们。
如果您使用的是现代 Java,请不要将您的实现 类 导出到您的模块之外。只导出public接口。
您还可以保留一个供内部使用的接口,其方法比 public API.
public interface Foo {
public void setBar(String bar);
public void setBaz(String baz);
}
@DynamoDBTable(tableName = "foo")
public class FooImpl implements Foo {
// Fields the client should be setting
private String bar;
private String baz;
// Fields the client should not access and should not care about. They are internal fields used for DynamoDB purposes.
private Long version;
private String gsiIndexKey;
// Empty constructor needed for deserialization of data from dynamodb
public FooImpl() {
}
// Getters and setters for all of the above fields.
@Override
public void setBar(String bar) {
this.bar = bar;
}
@Override
public void setBaz(String baz) {
this.baz = bar;
}
// Not part of the Foo interface
public void setVersion(Long version) {
this.version = version;
}
public void setGsiIndexKey(String indexKey) {
this.gsiIndexKey = indexKey;
}
}
我有一个构建在 DynamoDB 之上的 Spring 应用程序。我正在尝试编写一个 saveFoo()
存储库方法,它将 Foo
类型的对象保存到数据库中。该方法将从应用层调用。
我正在努力解决的问题是 Foo
class 中包含特定于 Dynamo 的字段。我不希望 saveFoo()
class 的客户认为他们需要使用这些字段创建类型为 Foo
的对象。我也不希望他们尝试自己设置这些值。
这些特定于数据库的字段需要 public getter 和 setter 才能与 DynamoDB SDK 一起使用。
数据库模型 class 如下所示:
@DynamoDBTable(tableName = "foo")
public class Foo {
// Fields the client should be setting
private String bar;
private String baz;
// Fields the client should not access and should not care about. They are internal fields used for DynamoDB purposes.
private Long version;
private String gsiIndexKey;
// Empty constructor needed for deserialization of data from dynamodb
public Foo() {
}
// Getters and setters for all of the above fields.
}
以及将对象保存到数据库的存储库方法:
public class FooRepositoryImpl {
public Foo saveFoo(WhatClassShouldThisBe foo) {
// Code that saves a new Foo item to the database and returns it.
}
}
我目前的想法是创建一个 FooWrapper 接口,saveFoo()
方法可以将其作为参数。包装器将允许客户端设置他们应该控制的字段,但不会公开与数据库内部相关的字段。类似下面的内容:
/**
* Allows us restrict visibility of the Foo fields to the Application by hiding database internal fields.
**/
public interface FooWrapper {
Foo getFoo()
}
public class FooWrapperImpl implements FooWrapper {
private final Foo foo;
public FooWrapperImpl(String bar, String baz) {
foo = new Foo();
foo.setBar(bar);
foo.setBaz(baz);
}
@Override
public Foo getFoo() {
return foo;
}
}
public class FooRepositoryImpl {
public Foo saveFoo(FooWrapper fooWrapper) {
Foo foo = fooWrapper.getFoo(); // Save this item to db
// Code that saves a new Foo item to the database and returns it.
}
}
您对这种方法有何看法?有谁知道我可以尝试一些更好的技术?我不禁觉得我在这里过度设计了东西。
仅向具有所需方法的客户端公开一个接口。在内部您可以调用实现的其他 public 方法,但客户端代码不会知道它们。
如果您使用的是现代 Java,请不要将您的实现 类 导出到您的模块之外。只导出public接口。
您还可以保留一个供内部使用的接口,其方法比 public API.
public interface Foo {
public void setBar(String bar);
public void setBaz(String baz);
}
@DynamoDBTable(tableName = "foo")
public class FooImpl implements Foo {
// Fields the client should be setting
private String bar;
private String baz;
// Fields the client should not access and should not care about. They are internal fields used for DynamoDB purposes.
private Long version;
private String gsiIndexKey;
// Empty constructor needed for deserialization of data from dynamodb
public FooImpl() {
}
// Getters and setters for all of the above fields.
@Override
public void setBar(String bar) {
this.bar = bar;
}
@Override
public void setBaz(String baz) {
this.baz = bar;
}
// Not part of the Foo interface
public void setVersion(Long version) {
this.version = version;
}
public void setGsiIndexKey(String indexKey) {
this.gsiIndexKey = indexKey;
}
}