首先让我说这更像是一个好奇心问题,因为正如您将看到的那样,我能够实现所需的功能。
但是,鉴于javascript是一种超级灵活的语言,我想看看其他开发者可能会想到这个问题:
我有一个从供应商函数返回的类的实例:
const connection = vendorDatabaseLib.createConnection();
现在,我想创建一个装饰器,它将为连接类添加功能,例如,重新连接逻辑。
让我们称之为PersistentConnection
。除了我添加的自定义函数之外,我希望PersistentConnection
的实例将所有函数调用转发到原始Connection
实例。并且在某些功能中覆盖了行为
我当然可以显式地实现所有Connection
的函数并将它们转发给内部对象,但可能有很多这些函数,所以我很快就放弃了这个想法。
以下是我对如何实现这一目标的看法:
PersistentConnection
的{{1}}类,然后修补供应商Connection
函数以返回vendorDatabaseLib.createConnection
而不是装饰器。我希望增加的功能。很诱人,但很糟糕。 PersistentConnection
个函数并动态创建转发,例如:
Connection
class PersistentConnection{
constructor(connection){
this._connection = connection;
// Iterate through all functions
for (prop in this._connection){
if(typeof(this._connection[prop]) === 'function'){
// Create functions dynamically for each forward
this[prop] = (...args) => {
this._connection[prop](...args);
}
}
}
}
// This is the added logic
reconnect(){
// Custom logic
}
}
实例设置为Connection
实例的原型:
PersistentConnection
这是我能想到的最“自动”的方式..但它只是非常难看,每次创建实例时都需要声明自定义函数。
我仍然觉得我错过了一些东西,比如Ruby的神奇function persistenChannel(channel){
const persistentChannel = {};
Object.setPrototypeOf(persistentChannel, channel);
persistentChannel.reconnect = () => {
// custom logic
}
}
(或pythons method_missing
)函数,它在抛出__getattr__
异常之前被调用,并让你定义“安全网”逻辑(如委托对内部method is missing
对象的所有调用
有没有更好的方法来实现此功能?
非常感谢[=
答案 0 :(得分:1)
让我们从我们拥有的东西开始。在任何情况下,大部分功能都将由供应商对象执行。我们不知道细节实现所以我们不能依赖这个对象没有状态。这意味着,在任何情况下,我们都需要新的persistentConnection的 new 连接对象。这可以通过proxy object
来实现让我们尝试这样做:
function Connection() {
this.connect = () => console.log('connected by Connection class');
this.disconnect = () => console.log('disconnected by Connection class');
}
function persistantConnectionFactory() {
function PersistentConnection() {
this.checkConnection = () => console.log('no connection');
}
const instance = new PersistentConnection();
const proxy = new Proxy(instance, {
get: function (target, name) {
if (!(name in target)) {
console.log('adding new prototype')
Object.setPrototypeOf(instance, new Connection())
}
return target[name];
}
});
return proxy;
}
var c = persistantConnectionFactory();
c.checkConnection();
c.connect();
这个解决方案好吗?我想不是。没有很好的理由,这会增加复杂性而没有任何价值原型应该足够了。