【问题标题】:Add information to interface向界面添加信息
【发布时间】:2013-12-24 10:49:56
【问题描述】:

连接.java

public interface Connect {
void commit();
void close();
void setTransactional();
void executeCommand();
}

MainApp.java

public class MainApp {
    public static void main(String[] args) {
        Connect conn=MainApp.getTransactionalConnection();
        conn.executeCommand();
        conn.executeCommand();
        conn.executeCommand();
        conn.executeCommand();
        closeConnection(conn);      
    }
    public static Connect getNormalConnection(){
        return DriverManager.getConnection(); //returns class i have no access to , dont even know its name
    }
    public static Connect getTransactionalConnection(){
        Connect conn =  getNormalConnection();
        conn.setTransactional();
        return conn;
    }
    private static void closeConnection(Connect conn) {
        //something like if connection is transactional then conn.commit();

        conn.close();
    }

}

我得到了 100 个看起来像 main() 的函数。问题是我不想更改这 100 个函数的代码,只需将 1 行 getNormalConnection 更改为 getTransactionalConnection 。我没有访问权限,也不知道实现 Connect 接口的类的名称。无论我是否创建了事务连接,我都只想向 closeConnection() 添加提交。

【问题讨论】:

    标签: java sql servlets connection


    【解决方案1】:

    一个简单的答案是拥有自己的Connect 实现,它要么公开isTransactional 属性,要么在事务性时自动提交,将其他所有内容委托给底层连接:

    public class AutoCommitConnect implements Connect {
        private final Connect connect;
        private boolean transactional = false;
        private boolean committed = false;
    
        public AutoCommitConnect(Connect delegate) {
            this.delegate = delegate;
        }
    
        public void commit() {
            delegate.commit();
            committed = true;
        }
    
        public void setTransactional() {
            transactional = true;
            delegate.setTransactional();
        }
    
        public void close() {
            if (transactional && !committed) {
                commit();
            }
            delegate.close();
        }
    
        public void executeCommand() {
            delegate.executeCommand();
        }
    }
    

    然后更改您的连接返回方法以使用它:

    public static Connect getNormalConnection() {
        // getTransactionalConnection will call setTransactional on the wrapper,
        // which will remember that it needs to commit
        return new AutoCommitConnect(DriverManager.getConnection());
    }
    

    【讨论】:

    • 但是当 Connect 包含 60 个方法时呢?他们每个人都必须“包装”。另一种可能的解决方案是制作外部地图,并使用布尔 isTransactional 保留引用。很容易实现,但是对于这种简单的情况不推荐吗?
    • @Zbigniew:到那时,这是一个不同的问题——总的来说,我会对这样的界面深表怀疑。包装很容易——体面的 IDE 可以为你生成所有代码,然后你只需要找出你想要以不同方式处理的方法。
    • pastebin.com/MfMvMAmT 在 c++ 中您对此有何看法?我知道它很丑;] 它可以工作,但我认为 fancyPointer 有时可以是一个随机数,甚至可能是“5”,所以它会失败。
    • @user3132199:目前还不清楚您为什么要将 C++ 引入图片中,或者您想要实现什么。不过,我不会将具有 getTransactionalConnect 的代码实现为 Connect 本身 - 我认为没有特别的原因。
    • 因为我想知道 Java 或 C# 中的等价物
    【解决方案2】:

    听起来您想要让接口的实现类具有某些方法的默认实现?
    你不能用接口来做到这一点,这就是抽象类的目的。这当然意味着您必须 extend 一个抽象类,而不是 implement 每个类中的一个接口。

    【讨论】:

    • 只是一个附加组件:在将接口更改为抽象类之前,您还应该记住,将接口更改为抽象类是二进制不兼容的更改。所有客户端代码都必须重新编译。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-14
    • 1970-01-01
    • 1970-01-01
    • 2011-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多