设计模式学习篇-代理模式

59 阅读1分钟

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