这是否违反了“依赖倒置原则”?

public class Connection {
public Connection(){

}

public String description() {
    return "Generic";
}

}

public class SqlServerConnection extends Connection{


public SqlServerConnection(){

}

public String description(){
    return "SQL Server";
}

}

public class OracleConnection extends Connection{
public OracleConnection(){

}

public String description(){
    return "Oracle";
}

}

public class MySqlConnection extends Connection{
public MySqlConnection(){

}

public String description(){
    return "MySQL";
}

}

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());
}

}

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

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

我可以通过这样做来解决这个问题吗?

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中(即通过接口将一个ConnectionFactory作为参数),而不是调用“new”来获得工厂。 这样TestConnection不依赖于Factory或Connection的具体实现。

工厂返回Connection的具体实现很好 - 事实上,如果你想实际使用连接,这是必要的。 您不依赖于特定的具体实现,因为工厂将其作为Connection(即作为接口)返回。 有人在某处确实需要实例化Connection实现 - 这是Factory的工作。

如果OracleConnection具有其他连接没有的某些方法,并且调用类取决于这些方法,那将是一种违规行为。 这里不是这种情况。


虽然可以说您的通用架构并不是实现数据库连接的最佳方式,但我会跳过这一点,因为我理解的问题是关于依赖倒置而不是数据库实现。 要实现完全依赖性倒转:

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

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

    这支持许多具体服务与服务客户的运行时关联的范例。 例如,在一个典型的启动时依赖注入场景中,你会将一个具体的ConnectionFactory实现注入到TestConnection ,然后它看起来像:

    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());
        }
    }
    

    这将TestConnection完全从任何数据库的依赖关系中分离出来,并且通过注入一个ConnectionFactory可以轻松配置它。 或者,也可以不执行“执行依赖注入”,而是执行服务查找。 J2EE / J3EE广泛使用它,例如从JNDI Context对象中获取ConnectionFactory(或更典型的是一个DataSource )。 这些超出了问题的范围,只是作为您想要这样做的一个例子,以及一种检查您是否满足该原则的方法。 对于来自外部资源(如数据库驱动程序)的任何内容, TestConnection只应该引用Interfaces而不是Classes。


    依赖倒置原则的原则是

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

    在你的情况下,你已经有了抽象的连接,这是很好的。 在我看来,工厂模式的使用也很好。

    B - 抽象不应该取决于细节。 细节应该取决于抽象。

    你的连接不依赖于较低的实现,并且继承的类可能使用Connection的方法/变量(如果这个例子可能更复杂)

    顺便说一句,我会倾向于使Connection成为一个抽象类,如果您稍后要添加更多的功能,并且不打扰为您制作的默认构造函数

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

    或者只是让它成为一个界面

    public interface Connection {
      String description();
    }
    
    链接地址: http://www.djcxy.com/p/82239.html

    上一篇: Does this violate the "Dependency Inversion Principle"?

    下一篇: Service Locator, Dependency Injection (and Container) and Inversion of Control