设计模式之代理模式
代理模式简介:为某对象提供一种代理以控制对该对象的访问。即客户端通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。比如,某对象需访问目标对象,但由于某种情况,不方便或不能直接访问目标对象,通过一个中介进行访问,这个中介就是代理对象。
代理模式结构
- 抽象接口类:可以是抽象类也可以是接口,代理类和实体类都需要显式实现它。
- 实体类:被委托的类,是具体业务的执行者。
- 代理类:负责对实体类的应用,并在实体类处理前后都增加预处理和处理后工作。
例子
模拟企业业务开发,完成每个功能的性能统计
定义一个UserService表示用户业务接口,规定必须完成用户登录,用户删除,用户查询功能。
定义一个实现类UserServiceImpl实现UserService,并完成相关功能,并统计每个功能耗时。
在不使用代理的情况下,我们是这么做的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| interface UserService{ login(loginName:string,password:string):void; deleteUsers():void; selectUsers():void;
}
class UserServiceImpl implements UserService{
login(loginName: string, password: string): void {
console.log("login性能测试开始。。。") if(loginName==="admin" && password === "123456"){ console.log("登录成功") }else{ console.log("账号密码错误") } console.log("login性能测试结束") }
deleteUsers(): void { console.log("deleteUsers性能测试开始。。。") console.log("您正在删除用户数据...") console.log("deleteUsers性能测试结束") }
selectUsers(): void { console.log("selectUsers性能测试开始。。。") console.log("查询了1000个用户数据...") console.log("selectUsers性能测试结束") } }
(() => { let user = new UserServiceImpl(); user.login("admin","123465"); user.selectUsers(); user.deleteUsers(); })
|
从上述代码可以看出,在每次进行业务操作时,我们都需要加入相同的代码(代码冗余),不利用代码复用,也违反了单一职责原则,UserServiceImpl
本用于进行用户的业务操作,却又加入了其他功能,增加类的复杂度。
下面使用动态代理,将代码改善:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
|
interface UserService { login(loginName: string, password: string): void; deleteUsers(): void; selectUsers(): void;
}
class DynamicProxy { public static getInstance(user: UserServiceImpl) { return new Proxy(user, { get(targetObj, propKey) { if (typeof targetObj[propKey as keyof typeof targetObj] === "function") { return new Proxy(targetObj[propKey as keyof typeof targetObj] as Function, {
apply: function (targetFunc: any, thisArg, argumentsList) {
console.log(propKey as string + "操作性能测试开始") if (propKey as string === "login") { targetFunc(argumentsList[0], argumentsList[1]) } else { targetFunc() } console.log(propKey as string + "操作性能测试结束") } }) }else{ return targetObj[propKey as keyof typeof targetObj] }
} }) } }
class UserServiceImpl implements UserService { val = 13 login(loginName: string, password: string): void {
if (loginName === "admin" && password === "123456") { console.log("登录成功") } else { console.log("账号密码错误") } }
deleteUsers(): void { console.log("您正在删除用户数据...") }
selectUsers(): void { console.log("查询了1000个用户数据...") } }
(() => { const user = DynamicProxy.getInstance(new UserServiceImpl()) user.login("ad", "132") user.deleteUsers() user.selectUsers() console.log(user.val)
})()
|
纵观整个程序,我们并没有在 UserServiceImpl 类中添加过多的职责,降低其耦合性,但通过代理对象,为系统添加了新的行为,这是符合开放-封闭原则的。就算有一天我们不再需要对操作进行性能测试,那么只需要把代理对象换成具体实现对象即可。