首页 » 技术分享 » 设计模式,就这么回事——访客模式

设计模式,就这么回事——访客模式

 

需求:优酷要求设计一个不同用户可以观看不同类别的视频资源的系统,这应该要用访客模式吧。
分析1:
一上来,先来个小学生的分析思维:得有不同的用户类,比如 普通用户 , 黄金用户 , 钻石用户 , 视频资源有 普通视频 , 黄金视频 , 钻石视频 。(钻石视频就是说钻石用户可看)对于不同的用户,展开鉴权。好了,开工:

class 用户()
{   看视频(视频)     }

class 普通用户()
{
    看视频( 视频 ){
        if 视频 == 普通视频 可以看;
        if 视频 == 黄金、钻石  不可以看;
    }
}
class 黄金用户()
{
    看视频( 视频 ){
        if 视频 == 普通 黄金视频 可以看;
        if 视频 == 钻石  不可以看;
    }
}
class 钻石用户()
{
    看视频( 视频 ){
        管你什么视频 都可以看;
    }
}

当然还有一些视频类:
class 普通视频,黄金视频,钻石视频;

//这样使用:
小明 = 普通用户()
视频 = 普通视频()
小明.看视频( 视频 )    OK
视频 = 黄金视频()
小明.看视频( 视频 )    NO

完工!感觉还可以。这算访客模式吗?当然不算!
优酷老总提要求了,说是要增加一档特别节目,比如成人节目,只允许 红宝石用户 观看,看看怎么修改代码:卧槽,代码全要改动:
首先要增加一个 成人节目 类;还要增加一个 红宝石用户 类 ;这些不说,坑爹的是所有之前的鉴权代码都要改,对于每一个用户 , 都要对 所有 视频进行遍历鉴权;。。。大概如下:

class 成人视频(){ 。。。 }
class 红宝石用户(){ 。。。 }
class 普通用户()
{
    看视频(视频)
    {
        if 视频 == 普通视频 可以看;
        if 视频 == 黄金、钻石  不可以看;
        //添加的部分
        if 视频 == 成人视频 不可以看;
    }
}
其他所有用户都要这样改。。。
如果哪天又推新节目,就废了。。。

评价1:上述方法,符合人的直观思维,易于理解。不过大量重复,也无封装、动态可言,实则是面向过程的设计。

分析2:
分析一下系统,特点如下:用户是变动的,视频是变动的,用户要和视频发生关系。并且视频的变动大于用户的变动。这很适合用访客模式。
这里主要解决的是 , 如何让 视频 的变动不影响用户的代码,如何让 视频 的变动不影响 用户 的代码。
先看第一个,如何让 视频 的变动不影响 用户。之前的系统是做不到这一点的,用户在 代码中遍历了 视频,视频改了用户代码也得改。其实,如果是用户 “访问”视频 的话,用户就依赖 视频,免不了跟着 视频 改动。何不转换一下思维方式,让 视频 ”访问“ 用户——对用户进行鉴权。这样,就变成视频 依赖 用户,至少可以解决第一个问题,就是 视频 变化不影响 用户 了。第二个问题如何解决后面再说。
好了,开工:

class 普通用户,黄金用户,钻石用户。。。随便加。。
//重点在下面
class 普通视频(){
    看视频( 用户 )
    if 用户 在普通之上  可以看;
}
class 黄金视频(){
    看视频( 用户 )
    if 用户 在黄金之上  可以看;
}
其他类似。
为了配合视频 “操作” 用户的这一特殊功能,我们得把用户类稍作改动。以普通用户为例,其他同。
class 普通用户(){
    看视频( 用户自己 , 视频 )
    视频.看视频( 用户自己 )
}
//上面是精华:在用户中,并不需要自己实现鉴权行为,而是交给 视频 类去处理,
//为了让 视频 能认识自己,还把自己作为参数传了进去,这下视频端就可以实现对用户的鉴权了。

那么怎么使用呢,像这样:
小明 = 普通用户()
视频 = 普通视频()
小明.看视频( 视频 )  OK~
视频 = 黄金视频()
小明.看视频(视频)  NO!

//如果哪天添加视频种类了,只需要这样即可
视频 = 成人视频()
小明.看视频( 视频 )
//根本不需要改用户代码,所有鉴权操作在 成人视频 中完成。

到这里,解决了一大问题,还有一个问题是,如何让 用户 的改动不影响 视频 , 现在 视频类 中要对 所有 用户 鉴权,视频其实是依赖用户的,对这种依赖的一个应对策略就是 保证用户类别的稳定性。没有什么办法比这个办法更好了。
是在不行,再使用如下方法:
在视频类中,放一份用户类别列表,这份列表由 用户工厂 维护。视频 类需要从 用户 工厂中 获取到这个 列表,然后对里面的用户 遍历鉴权。这样也能做到即使 用户变化了,视频 类也无需改动 , 因为视频类 内部处理的是 用户列表,至于有几个用户,无关紧要。
大致如下实现视频类:

class 视频(){
    用户列表 = 用户工厂.get用户列表()
    for 用户 in 用户列表{
        鉴权。。
    }
}

到此,两大问题都解决了。设计完之后,聪明的你可能会发现,用户 和 视频 地位其实是对等的。能用 视频 访问 用户的思路解决问题,其实原来的 用户 访问 视频 也能解决问题。的确如此,用户访问视频模式 ,首先用户的变化不影响视频,其次,用一个视频列表就可以解决视频的变化不影响用户。只不过,访客模式强调的访客的稳定性,即这里的用户是稳定的,如果要设计,就得让用户成为 被访问 对象。说白了,两个类发生关系,哪个类稳定,就让哪个类充当 被处理者。这,就是访客模式。

转载自原文链接, 如需删除请联系管理员。

原文链接:设计模式,就这么回事——访客模式,转载请注明来源!

0