Java 这是否违反了「;依赖倒置原则;?

Java 这是否违反了「;依赖倒置原则;?,java,design-patterns,dependency-inversion,Java,Design Patterns,Dependency Inversion,} } } } } } 这是VTC设计模式视频教程,我的问题是这个例子是否违反了依赖倒置原则 因为TestConnection类依赖于具体实现,因为factory.createConnection()返回具体实现而不是抽象 我可以改为这样做吗 public class TestConnection { public static void main(String[] args) { FirstFactory factory; factory = new Firs

}

}

}

}

}

}

这是VTC设计模式视频教程,我的问题是这个例子是否违反了依赖倒置原则

因为TestConnection类依赖于具体实现,因为factory.createConnection()返回具体实现而不是抽象

我可以改为这样做吗

public class TestConnection {
public static void main(String[] args) {
        FirstFactory factory;

        factory = new FirstFactory("Oracle");

        Connection connection = factory.createConnection(); //createConnection return concrete implementation not an abstraction

        System.out.println("You're connection with " + connection.description());
}

}

您建议的两种
createConnection
实现是等效的;返回连接的方向与将连接存储在变量中并返回连接之间没有功能上的区别


至于是否存在一些违反依赖性反转的情况,我想说,工厂是有点好的,这取决于它打算如何使用。您希望类将
连接
作为参数,而不是直接调用工厂来获取连接。

理想情况下,您应该将工厂注入TestConnection(即,它将通过接口将ConnectionFactory作为参数),而不是调用“new”来获取工厂。这样,TestConnection既不依赖于工厂的具体实现,也不依赖于连接的具体实现

工厂返回一个连接的具体实现是很好的——事实上,如果您想实际使用连接,这是必要的。您不依赖于特定的具体实现,因为工厂将其作为连接(即作为接口)返回。某些人,某些地方确实需要实例化连接实现——这是工厂的工作


如果OracleConnection具有其他连接不具有的某些方法,并且调用类依赖于这些方法,那么这将是一种违反。这里的情况并非如此。

虽然可以说您的通用体系结构不是实现数据库连接的最佳方式,但我将跳过这一点,因为我理解的问题更多的是依赖关系反转,而不是数据库实现。要实现完全依赖项反转,请执行以下操作:

  • 连接
    应该是一个接口,而不是一个具体的类
  • ConnectionFactory
    应该是一个接口,而不是一个具体的类,它定义了一个
    createConnection()
    方法,返回一个
    连接。它的构造函数中不需要参数
  • 对于每个数据库,您将有一个不同的具体类来实现
    ConnectionFactory
    ,并返回实现
    Connection
    的对象
以上更好地满足了依赖倒置原则,因为现在TestConnection只指定了它从服务提供者那里需要什么,而没有耦合到任何具体的实现。任何具体的实现都可以创建和使用,只要它满足为TestConnection定义的接口指定的要求,并且接口指定的内容不超过TestConnection真正需要的内容

特别是,另一个包中的另一个供应商可以创建新的
工厂
连接
实现,您可以将其插入代码中(如果您遵循上述体系结构),并且您的
测试连接
类不需要任何修改

这支持将具体服务与服务客户机的运行时关联的许多范例。例如,在一个典型的启动时依赖项注入场景中,您将
ConnectionFactory
的具体实现注入
TestConnection
中,然后它将如下所示:

public Connection createConnection(){

Connection connection = null;

if(type.equals("Oracle")){
    connection = new OracleConnection();
}else if(type.equals("SQL Server")){
    connection = new SqlServerConnection();
}else{
    connection = new MySqlServerConnection();
}
return connection;

这将TestConnection与任何数据库上的任何依赖完全分离,并通过注入一个
连接工厂
使其易于配置。或者,您可以执行服务查找,而不是“执行依赖项注入”。J2EE/J3EE广泛使用它,例如从JNDI
上下文
对象中获取连接工厂(或者更典型的是
数据源
)。这些都超出了问题的范围,只是提供了一个示例,说明您为什么要这样做,以及一种检查您是否满足原则的方法<对于来自外部源(如数据库驱动程序)的任何内容,code>TestConnection
应该只引用接口,而不是类

依赖项反转原理的主体是

A-高级模块不应依赖于低级模块。两者都应该依赖于抽象

在您的例子中,您已经抽象了连接,这是很好的。在我看来,工厂模式的使用也很好

抽象不应该依赖于细节。细节应该取决于抽象

您的连接不依赖于较低的实现,继承的类可能使用连接的方法/变量(如果示例更复杂,它们可能会使用)

顺便说一句,我倾向于使连接成为一个抽象类,如果您以后要向它添加更多功能,而不必担心为您设计的默认构造函数的话

public class TestConnection {
    private ConnectionFactory connectionFactory;
    public setConnectionFactory(ConnectionFactory connectionFactory) {
        this.connectionFactory = connectionFactory;
    }

    public static void main(String[] args) {

        //
        // Perform dependency injection here
        //

        // after dependency injection

        Connection connection = connectionFactory.createConnection(); //createConnection return concrete implementation not an abstraction

        System.out.println("You're connection with " + connection.description());
    }
}
或者只是让它成为一个界面

public class Connection {
  public abstract String description();
}

我将连接存储到它的接口中,所以我假设它的程序到接口。所以也许我错了。你们真的希望连接是一个接口,而不是一个类。您不希望其他提供程序被迫扩展您的连接类。这看起来像依赖项注入。虽然经常结合使用,但我认为依赖项反转原则是一种不同的模式。@Bruce,我将澄清答案,但简而言之,最重要的要点描述了如何构建符合依赖项反转原则的解决方案,其余的则展示了一个示例,说明了如何使用依赖项反转原则以及它将带来什么好处。在我的示例中,我选择了依赖注入,但您也可以轻松地创建一个示例usi
public class FirstFactory {
String type;

public FirstFactory(String t){
    type = t;
}

public Connection createConnection(){
    if(type.equals("Oracle")){
        return new OracleConnection();
    }else if(type.equals("SQL Server")){
        return new SqlServerConnection();
    }else{
        return new MySqlConnection();
    }
}
public class TestConnection {
public static void main(String[] args) {
        FirstFactory factory;

        factory = new FirstFactory("Oracle");

        Connection connection = factory.createConnection(); //createConnection return concrete implementation not an abstraction

        System.out.println("You're connection with " + connection.description());
}
public Connection createConnection(){

Connection connection = null;

if(type.equals("Oracle")){
    connection = new OracleConnection();
}else if(type.equals("SQL Server")){
    connection = new SqlServerConnection();
}else{
    connection = new MySqlServerConnection();
}
return connection;
public class TestConnection {
    private ConnectionFactory connectionFactory;
    public setConnectionFactory(ConnectionFactory connectionFactory) {
        this.connectionFactory = connectionFactory;
    }

    public static void main(String[] args) {

        //
        // Perform dependency injection here
        //

        // after dependency injection

        Connection connection = connectionFactory.createConnection(); //createConnection return concrete implementation not an abstraction

        System.out.println("You're connection with " + connection.description());
    }
}
public class Connection {
  public abstract String description();
}
public interface Connection {
  String description();
}