我想知道如何在以下示例中最好地分离责任。
有Foo
个对象包含一些id
和一些reallySecretImportantData
字段。 Id是用于引用对象的简单标识符,而reallySecretImportantData
是应该在数据库中加密的数据,因为数据库是此示例中唯一易受攻击的点。
现在,如果我们有一个FooService
方法void storeFoo(Foo foo)
和Foo readFoo(Id id)
。
我们还有一个FooRepository
,它有标准的CRUD方法,可以将Foo对象存储在数据库中。
现在,由于我想保存reallySecretImportantData
加密,我必须在某处加密并在某处解密。
由于FooRepository
的责任不应包括加密操作,因此逻辑位置为FooService
。
现在,如果我在某个开发环境中,出于开发和测试的目的,我希望以纯文本格式保存reallySecretImportantData
。
如果我使用某种DI,我可以编写我的服务的2个实现,一个用于prod,另一个用于dev / test,并且只需配置DI以在生产环境中使用prod和在dev& test中使用dev / test环境。
现在,如果在不久的将来出现了更改reallySecretImportantData
存储方式的请求,我可以简单地编写该服务的另一个实现并使用我的DI框架来注入它。
这个简单的设计对于当前的模型案例是否足够好?
答案 0 :(得分:1)
您的设计让我想起strategy pattern. FooService
可以被视为战略界面。
但我更喜欢将encrypt()
和decrypt()
方法添加到此界面,而不是store()
和read()
。我们可以将其命名为FooCryptoStrategy
。
此外,FooRepository
可以用FooCryptoStrategy
对象构造。
因此,您可以CRUD Foo
对象不考虑加密问题。
您可以为发布和测试创建多个FooCryptoStrategy
实现。即使你可以实现NonCryptoStrategy
。
总之,使用策略模式,我们可以将一个责任分配给一个类:
Foo
:存储数据
FooCryptoStrategy
:加密和解密Foo
个对象
FooRepository
:使Foo对象持久化。
控制器类:创建具体的FooCryptoStrategy
和FooRepository
对象。
答案 1 :(得分:0)
为什么需要"服务"?
考虑一个知道如何en / de / crypt的Secret
对象,以及一个处理持久性的数据管理对象。
使您的功能"可插拔"通过使用通用接口实现加密算法,例如IEncrypt。例如,你可能有一个AesEncryptor和一个TestPlainEncryptor
// simple non-dependency-injection example
Secret encrypted = new Secret(new AesEncryptor, "key", "my secret stuff");
new SecretDM().Save(s);
Secret retrieved = new SecretDM().Get("key");
// println(retrieved.Decrypt());