1.概念
在不改变原始类(或者称为被代理类)的情况下,给原始类附加新功能。
2.为什么使用原始类
在游戏开发中,比如我们要临时打印登录服务器需要的耗时,在登录逻辑代码不受侵入修改时,我们就可以使用代理类来实现打印耗时操作。一般情况下,我们让代理类和原始类实现同样的接口。但是,如果原始类并没有定义接口,并且原始类代码并不是我们开发维护的。在这种情况下,我们可以通过让代理类继承原始类的方法来实现代理模式。
3. 代码实现
interface ILogin {
Login();
}
class Login implements ILogin {
async Login() {
// throw new Error("Method not implemented.");
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
class LoginProxy implements ILogin {
private _login: Login;
private _start_time: number;
constructor(login: ILogin) {
this._login = login;
}
async Login() {
// throw new Error("Method not implemented.");
console.log('login proxy');
this._start_time = Date.now();
await this._login.Login();
console.log(Date.now() - this._start_time);
}
}
// 具体使用,需要的操作只是把login从new Login()替换成new LoginProxy();
let login = new LoginProxy(new Login());
login.Login();
4.动态代理
如果需要知道每个方法执行的时间,可以通过动态代理的形式来创建,代码如下:
class Login {
Login() {
console.log('login step');
// throw new Error("Method not implemented.");
// await new Promise(resolve => setTimeout(resolve, 1000));
}
Register() {
console.log('register step');
}
Logout(){
console.log('logout step');
}
}
class DynamicCreateProxy {
public createProxy(obj: object): object {
Reflect.ownKeys(obj.constructor.prototype).forEach(key => {
if (typeof obj[key] === 'function' && key !== 'constructor') {
let old = obj[key];
obj[key] = (...args) => {
let now = Date.now();
Reflect.apply(old, obj, args);
console.log(Date.now() - now);
}
}
})
return obj;
}
}
let proxy = new DynamicCreateProxy();
let login = proxy.createProxy(new Login()) as Login;
login.Login();
login.Register();
login.Logout();