java - 无法使用多态访问具体类的唯一属性

标签 java design-patterns

我正在使用工厂模式在 java version "1.7.0_60" 中创建不同连接的对象

我面临的问题是每个具体类都将具有该特定类的唯一属性。由于工厂在返回具体类的实例时将使用多态性,因此我无法访问唯一属性。即 getHostType() 仅对 SqlServerConnection 是唯一的。

我所做的解决方法是在父类(super class)中声明 getHostType() 抽象并在每个具体类中实现它。但是,我真的不想那样做,因为我添加的具有独特属性的具体类越多,我就必须在父类(super class)中包含越多的抽象方法,然后在每个具体类中实现它们。

我想保留我的工厂模式和抽象父类(super class)。我只是想知道是否有任何其他方法可以代替父类(super class)中的抽象方法?我可以包含任何设计模式来解决这个问题吗?

public abstract class Connection {
    private int port;
    private int ipAddress;

    public Connection() {}

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

    /* Implement in every concrete class, even if the concrete type doesn't have that property */
    public abstract int getHostType();
}

public class SqlServerConnection extends Connection {
    private int sqlHostType;

    public SqlServerConnection() {
        sqlHostType = 5060;
    }

    @Override
    public String description() {
        return "Created a Sql Server connection type";
    }

    @Override
    public int getHostType() {
        return sqlHostType;
    }
}

public class OracleConnection extends Connection {
    public OracleConnection() {}

    @Override
    public String description() {
        return "Created an Oracle connection type";
    }
}

final public class ConnectionFactory {
    protected String mType;

    public ConnectionFactory(String type) {
        mType = type;
    }

    /* Create the connection we want to use */
    public Connection createConnection() {
        if(mType.equals("Oracle")) {
            return new OracleConnection();
        }
        else if(mType.equals("SQLServer")) {
            return new SqlServerConnection();
        }
        else {
            return null;
        }
    }
}

public class TestConnection {
    public static void main(String[] args) {
        ConnectionFactory factory = new ConnectionFactory("SQLServer");
        Connection conn = factory.createConnection();

        conn = factory.createConnection();
        System.out.println(conn.description());
        /* need to access the getHostType() */
        System.out.println(conn.getHostType());
    }
}

最佳答案

您应该看看访问者模式。您需要声明一个接口(interface) ConnectionVisitor 并为层次结构中的每个连接类添加一个方法访问。

public interface ConnectionVisitor {

    public int visit (Connection connection);
    public int visit (SqlServerConnection sqlconnection);
    public int visit (OracleConnection oracleConnection)
}

现在您需要在基类连接中添加一个接受方法,该方法接受一个 ConnectionVisitor,然后对其调用访问。您的新连接类看起来像

public abstract class Connection {
  private int port;
  private int ipAddress;

  public Connection() {}

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

  public int accept(ConnectionVisitor visitor){
     return visitor.visit(this);
  }

请注意,accept 方法执行双重分派(dispatch)。它根据调用它的对象和传递给此方法的参数进行分派(dispatch)。这是访问者模式的核心。

然后您可以实现 ConnectionVisitor 接口(interface)来定义任何新功能,而无需更改您的基类。

class   DemoVisitor implements ConnectionVisitor{
  public  int visit(Connection connection){
     System.out.println("Visiting Connection");
     return 1;
  }

  public int visit(SqlServerConnection sqlServerConnection){
     System.out.println("Visiting SqlServerConnection");
     return 1;
  }

  public  int visit(OracleConnection oracleConnection){
     System.out.println("Visiting Oracle Connection");
     return 1;
  }

在您的 TestConnection 类中,您可以简单地创建一个新的连接对象,然后对该对象调用 accept 方法并传递一个访问者对象。

public class TestConnection {
  public static void main(String[] args) {
    ConnectionFactory factory = new ConnectionFactory("SQLServer");
    Connection conn = factory.createConnection();

    conn = factory.createConnection();
    System.out.println(conn.description());
    ConnectionVisitor visitor = new DemoVisitor();
    System.out.println(conn.accept(visitor));
  }

因此,现在任何特定于子类的功能都不能驻留在连接类层次结构中,而必须在新访问者中实现。

请注意,此模式不适合您的场景。这种模式的限制之一是访问者接口(interface)中所有方法的返回类型必须相同。这种模式可能适合也可能不适合您的需要,但值得研究您的情况。您可能需要修改此模式以满足您的需要。这就是模式的全部意义在于研究一些常见的解决方案,然后修改这些解决方案以适应您的问题。

关于java - 无法使用多态访问具体类的唯一属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24778774/

相关文章:

Java 作业,迷失在数学中

c# - 构造异常消息的最佳做法是什么?

python - 指向另一个对象的属性并添加你自己的

java - 根据对象值实例化特定类

java - 如何在 Kotlin 中解析 Volley 中来自服务器的错误

java - JPanel 添加背景

java - 使用JAVA将大型2D数组分解为多个较小的2D数组

java - 我应该如何访问 ThreadPoolExecutor 中 beforeExecute 和 afterExecute Hook 中的类成员?

java - 删除重复代码的模式

c++ - C++中的“Poor Man'反射”(又名自下而上的反射)