单一责任原则和服务/存储库设计

时间:2015-12-15 10:27:02

标签: java oop encryption single-responsibility-principle

我想知道如何在以下示例中最好地分离责任。

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框架来注入它。

这个简单的设计对于当前的模型案例是否足够好?

2 个答案:

答案 0 :(得分:1)

您的设计让我想起strategy pattern. FooService可以被视为战略界面。

但我更喜欢将encrypt()decrypt()方法添加到此界面,而不是store()read()。我们可以将其命名为FooCryptoStrategy

此外,FooRepository可以用FooCryptoStrategy对象构造。 因此,您可以CRUD Foo对象不考虑加密问题。 您可以为发布和测试创建多个FooCryptoStrategy实现。即使你可以实现NonCryptoStrategy

总之,使用策略模式,我们可以将一个责任分配给一个类:
Foo:存储数据
FooCryptoStrategy:加密和解密Foo个对象
FooRepository:使Foo对象持久化。
控制器类:创建具体的FooCryptoStrategyFooRepository对象。

答案 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());