Python中文网

一个关于 编程问题的解答网站.

有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

带有使用不同参数的构造函数的oop Java简单工厂

我有两种在应用程序中保存数据的方法:保存到数据库和保存到文件。因为我不想让客户机代码处理对象的构造,所以我创建了一个类(据我所知)是一个带有工厂方法的简单工厂。代码如下:

public static DataPersister createDataPersister(Boolean saveToDb, Session session, String filename) {
    if (saveToDb) {
        return new DatabaseDataPersister(session);
    } else {
        return new FileDataPersister(filename);
    }
}

使用此设置,客户端代码不必构造任何内容,也不必决定是否保存到DB或文件,它只需对工厂返回的对象调用save()方法,如下所示:

DataPersister dataPersister = DataPersisterSimpleFactory.createDataPersister(this.savetoDb, this.session, this.filename);
dataPersister.save(this.data);

我的问题是——这个解决方案是否违反了坚实的原则?为了创建一个DatabaseDataPersister客户端代码需要传递一个filename参数,而DataPersister的这个实现将不会使用它。我觉得它和界面隔离原则不太一样,但不是那样

如果解决方案确实是一种代码气味,我该如何清洗它


共 (2) 个答案

  1. # 1 楼答案

    我认为违反的可靠原则是DIP

    通过直接依赖静态工厂,您的客户机类在编译时依赖于实际实现DatabaseDataPersisterFileDataPersister,而不仅仅是抽象DataPersister

    要解决这个问题,请向客户机提供您希望他们使用的DataPersister。建造师通常是这样做的好地方:

    public class ExampleClient {
    
        private final DataPersister dataPersister;
    
        public ExampleClient(DataPersister dataPersister) {
            this.dataPersister = dataPersister;
        }
    
        public void methodThatUsesSave(){
            dataPersister.save(data);
        }
    }
    

    这段代码编译时没有具体的实现,也就是说,它不依赖于具体的实现。客户机也不需要知道filenamesession,所以它也解决了代码的气味

    我们可以在施工时决定采用哪种具体实施方式,这里我使用您现有的方法:

    DataPersister dataPersister = DataPersisterSimpleFactory.createDataPersister(this.savetoDb, this.session, this.filename);
    ExampleClient example = new ExampleClient(dataPersister);
    
  2. # 2 楼答案

    这里正确的解决方案是将韦斯顿的依赖注入和OldCurmudgeon的工厂模式结合起来

    public class ExampleClient {
    
        private final DataPersister dataPersister;
    
        public ExampleClient(DataPersister dataPersister) {
            this.dataPersister = dataPersister;
        }
    
        public void methodThatUsesSave(){
            dataPersister.save(data);
        }
    }
    
    class PersisterFactory {
        public DataPersister createDatabasePersister(Session session) {
            return new DatabasePersister(session);
        }
    
        public DataPersister createFilePersister(String filename) {
            return new FilePersister(filename);
        }
    }
    

    上层代码:

    PersisterFactory = new PersisterFactory();
    DataPersister dataPersister;
    if (saveToDb)
        dataPersister = PersisterFactory.createDatabasePersister(new Session());
    else
        dataPersister = PersisterFactory.createFilePersister("Hello");
    ExampleClient example = new ExampleClient(dataPersister);
    

    通常dataPersister来自DI容器,而saveToDb来自配置,但测试当然可能是一个例外