🔥【设计模式】策略模式

191 阅读3分钟

最新更文通知.png 小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

大家好,我是“前端小鑫同学”,😇长期从事前端开发,安卓开发,热衷技术,在编程路上越走越远~


场景介绍:

我们有一款识视频App,目前可以登录的用户分为临时用户、普通用户、管理员三种,还有会员等级的一个分类,主要有无会员、普通会员,高级会员。在最初设计稿中指明,可以观赏高清视频的只能是普通用户并且开通了高级会员,可以登录管理平台的支能是管理员。

需求描述:

根据上面的描述我们先准备一个权限和一个会员的枚举:

// 1. 临时用户/普通用户/管理员
enum Role {
  casual,
  general,
  admin
}

// 2. 无会员/普通会员/高级会员
enum Members {
  non,
  general,
  senior
}

初次编写我们总是会选择最快捷的编码方式,如下面这种:

haveAuthorized(user, tag){
  if(tag === "HdVideo") {
    // 是否享有高清视频浏览的权限
  	return user.role === Role.general && user.members === Members.senior;
  } else if(tag === "admin") {
    // 是否享有管理员的权限
    return user.role === Role.admin;
  }
}

这样的代码当然可以用了,但是往远的考虑,多数平台的权限规则往往是随着平台的迭代而变化的,那这样的话,这个函数将会逐渐变大,难以维护,因为我们模拟的时候只是简单的判断,实际项目中往往还会配合着数据库的查询等等更为复杂的处理,各式各样的权限要求加复杂的算法的情况下我们考虑使用策略模式来进行一次优化。

使用策略模式进行优化

我们的代码在ts环境编写,懒得搭建ts环境的可以使用在线的编辑器:如:codesandbox.io/

1. 创建一个策略基类

  1. 添加所需策略
  2. 校验是否满足策略
class BaseStrategy {
  strategies: any = {};
  cache: any[] = [];

  addStrategy(value: number, method: string) {
    this.cache.push(() => {
      return this.strategies[method](value);
    });
  }

  validator() {
    if (this.cache.length !== Object.keys(this.strategies).length) {
      return false;
    }
    for (let i = 0; i < this.cache.length; i++) {
      var data = this.cache[i]();
      if (!data) {
        return false;
      }
    }
    return true;
  }
}

2. 基于基类来创建高清视频观赏策略和管理员策略

// 高清视频观赏策略
class HdVideoViewingStrategy extends BaseStrategy {
  constructor() {
    super();
    this.strategies = {
      checkRole: (value: number) => {
        return value === Role.general;
      },
      checkMembers: (value: number) => {
        return value === Members.senior;
      }
    };
  }
}

// 管理平台登录权限
class ManagementPlatformStrategy extends BaseStrategy {
  constructor() {
    super();
    this.strategies = {
      checkRole: (value: number) => {
        return value === Role.admin;
      }
    };
  }
}

3. 来模拟看一下吧

用户user1:普通用户,高级会员,符合高清视频浏览,结果应为享有权限。

const user1 = {
  role: Role.general,
  members: Members.senior
};

// 策略+组合模式
const hdVideoStrategy = new HdVideoViewingStrategy();
hdVideoStrategy.addStrategy(user1.role, "checkRole");
hdVideoStrategy.addStrategy(user1.members, "checkMembers");

// 检查权限是否满足
console.log(
  "是否享有高清视频观赏权限: ",
  hdVideoStrategy.validator() ? "享有" : "不享有"
);

用户user2:管理员,符合管理平台登录策略,结果为享有权限内。

// 用户信息
const user2 = {
  role: Role.admin
};

// 策略+组合模式
const mpStrategy = new ManagementPlatformStrategy();
mpStrategy.addStrategy(user2.role, "checkRole");

// 检查权限是否满足
console.log(
  "是否允许登录管理平台: ",
  mpStrategy.validator() ? "可以" : "不可以"
);

总结:

暂时性的代码量增加了不少,但是我们在新增和修改策略的时候变得更加的明确,复杂的算法也从haveAuthorized方法中抽离到了指定的策略中,虽说不应该为了设计模式而用设计模式,但是下次一定要在项目中用一用。多看,多思考,多写,多总结。


欢迎关注我的公众号“前端小鑫同学”,原创技术文章第一时间推送。