作者:Hmily-西瓜先生 | 来源:互联网 | 2023-10-12 13:02
我有两种在应用程序中保存数据的方式:保存到数据库和保存到文件.因为我不希望使用客户端代码来处理对象的构造,所以我创建了一个类(据我所知)是带有工厂方法的简单工厂.代码如下:
我有两种在应用程序中保存数据的方式:保存到数据库和保存到文件.因为我不希望使用客户端代码来处理对象的构造,所以我创建了一个类(据我所知)是带有工厂方法的简单工厂.代码如下:
public static DataPersister createDataPersister(Boolean saveToDb, Session session, String filename) {
if (saveToDb) {
return new DatabaseDataPersister(session);
} else {
return new FileDataPersister(filename);
}
}
使用此设置,客户端代码不必处理任何构造或决定是否保存到数据库或文件的操作,它可以仅对工厂返回的对象调用save()方法,如下所示:
DataPersister dataPersister = DataPersisterSimpleFactory.createDataPersister(this.savetoDb, this.session, this.filename);
dataPersister.save(this.data);
我的问题是-此解决方案是否违反SOLID原则?为了创建例如DatabaseDataPersister客户端代码需要传递文件名参数,而DataPersister的此实现将不使用它.我觉得它不适合与接口隔离原理类似的东西,但事实并非如此.
并且,如果解决方案的确是有代码气味的,该如何清洁?
解决方法:
我认为违反的SOLID原则是DIP.
您的客户端类必须直接依赖于静态工厂,因此在编译时依赖于实际的实现DatabaseDataPersister和FileDataPersister,而不仅仅是抽象的DataPersister.
要解决此问题,请向客户端提供您希望他们使用的DataPersister.构造函数通常是个好地方:
public class ExampleClient {
private final DataPersister dataPersister;
public ExampleClient(DataPersister dataPersister) {
this.dataPersister = dataPersister;
}
public void methodThatUsesSave(){
dataPersister.save(data);
}
}
该代码在没有具体实现的情况下进行编译,即不依赖于它们.客户端也不需要知道文件名或会话,因此它也可以解决代码异味.
我们可以决定在构建时提供哪种具体实现,这里我使用您现有的方法:
DataPersister dataPersister = DataPersisterSimpleFactory.createDataPersister(this.savetoDb, this.session, this.filename);
ExampleClient example = new ExampleClient(dataPersister);