专注收集记录技术开发学习笔记、技术难点、解决方案
网站信息搜索 >> 请输入关键词:
您当前的位置: 首页 > 图形/图像

可配备权限的图形用户界面框架的分析和实现

发布时间:2011-06-27 20:22:08 文章来源:www.iduyao.cn 采编人员:星星草
可配置权限的图形用户界面框架的分析和实现

1. 前言

作为一个图形用户界面开发人员,都会被繁复的界面呈现权限逻辑困扰过,多年来,界面开发的编写方式没有太大的改变,界面程序中总是掺杂着许多条件判断语句,本文的目的就是对这种问题的分析和解决。

 

希望对这种类型的GUI框架有研究的网友能发表自己的看法,多多交流。

2. 切入点

本文的切入点在于根据不同的条件判断语句显示控件,这是界面逻辑的主体。

3. 阅读要求

需要阅读者基于GUI框架写过程序,诸如MFC, VCL, wxWidgets,或者struts, webwork之类,其他语言的GUI框架也行。

4. 第一阶段--现状

仍然用我的老朋友--请假单作为案例,以下人名纯属虚构,如有巧合,纯属偶然。一张请假单在普通员工填写时,请假原因一栏是可读写的。

 

但是当部门经理和其他角色阅读时,为只读状态。

如果是用编程语言实现权限判断,那么伪码为

if (普通员工角色.包含(当前用户)) {

  (new TextArea("请假原因")).draw();

else if (经理角色.包含(当前用户)) {

  (new Text("请假原因")).draw();

}

如果是struts,那么标签伪码为

<c:if  test="普通员工.包含(当前用户)">

  <html:textarea id="请假原因"/>

</c:if>

<c:if  test="经理角色.包含(当前用户)">

  <html:text id="请假原因"/>

</c:if>

 

通过上面的例子,我们看到为了在两种角色下分别呈现请假原因控件,写了两段,可以联想到如果有更多的角色要查看同一个页面时会发生什么事--更多的权限判断代码+更多的同id控件输出,就算封装得再漂亮,但只要不改变这种写代码的本质,情况就不会改变。这种同一个id的控件写上多次的情况,是造成编码量急剧增加且难以维护的主要原因。

5. 第二阶段--分析和实现

要实现权限可配置,除非权限也是对象,那么干脆就假设权限是对象,定义相关规则如下。

将权限作为独立对象。

那么将上面的代码用对象模型用来表达,如下

同时也要解决同名id控件的重复性问题,则假设控件可以根据权限自动决定如何呈现界面,相同id的控件实际只为1个。那么对象模型就变成下面的图

 

 

很容易看出,现在的我们只是要对权限和控件两坨对象之间进行逻辑关联,以确定如何呈现界面。

再定义出如下几条规则,以方便编写代码:

 

控件使用权限对象引用来和权限对象绑定。

将权限引用包含到控件内。

 

现在,伪码变成这样

<ScriptRight id="普通员工权限" script="普通员工角色.包含(当前用户)"/>

<ScriptRight id="经理权限" script="经理角色.包含(当前用户)"/>

 

<Textarea id="请假原因">

  <RightRef id="普通员工权限" value="读写"/>

  <RightRef id="经理权限" value="只读"/>

</Textarea>

 

似曾相识吧?没错,类似Ant里Path和PathRef标签的写法。

现在代码完全的对象化了,结构清晰。控件越多这种写法的优势越明显。...

当然,上面的规则不是很完整,为了能够实现控件自决定呈现,得加上几条:

 

权限值有 读写、只读、隐藏、禁止 四种。

权限值为读写时调用控件的界面呈现方法。

权限值不为读写时由控件在内部决定类型转换,然后调用转换后对象的呈现方法--默认情况下只读转换为文本,隐藏转换为hidden标签,禁止则删除该对象。

 

这样的规则复杂度一般般,要想实现把呈现的变换隐藏到控件内部,则将权限值当作独特的状态值来看待,使用《设计模式》中的状态模式就可以了。

 

到目前为止,离实用还有点距离,灵活性还不够,因为在权限改变时,控件的属性会改变,比如,对于提交按钮来说,提交时的javascript处理函数会改变,假设需求如下:

在其他权限时,生成html代码

<input type='submit' id='提交' value='提交' onclick='doA()'/>

但在经理权限时,要生成

<input type='submit' id='提交' value='提交' onclick='doB()'/>

 

因此再订一条规则来包容属性变化:

允许在权限匹配时,修改控件的属性。

假设我们有如下需求

下面是示例代码

<ScriptRight id="普通员工权限" script="普通员工角色.包含(当前用户)"/>

<ScriptRight id="经理权限" script="经理角色.包含(当前用户)"/>

 

<SubmitButton id="提交">

  <HTMLAttributes onclick="funcA()" style="color:blue"/>

  <RightRef id="普通员工权限" value="读写"/>

  <RightRef id="经理权限" value="读写">

    <field name="HTMLAttributes.onclick" value="doB()"/>

  </RightRef>

</SubmitButton >

现在对上面的代码说明。

 

HTMLAttributes是SubmitButton标签对应的处理类SubmitButton的属性,类图如下

大部分开源框架配置文件xml元素对应的处理类都是这么写的,规则为:

同名的标签对应同名的类。

同名的属性对应同名的参数或者子标签。

在这里,HTMLAttributes子标签里的所有参数,将原封不动的生成为HTML字符串(也可以考虑支持EL表达式),在权限引用(RightRef)标签里,子标签field表示,符合本权限时,将

Name参数值对应的控件对象的属性值按照反射规则重写。用java伪码表达就是

/* 本例中

 * fieldName = "HTMLAttributes.field";

 * fieldValue = "doB()";

 */

public void setField(Object control, String fieldName, Object fieldValue) {

  if (fieldName.contains(".")) {

    String[] fieldNames = fieldName.split(".");

    Object field = BeanUtil.getProperty(control, fieldNames[0]);

    if (field.getType() == Map) {

      ((Map)field).put(fieldNames[1], fieldValue);

    }

  }

}

 

虽然可实现本例的功能,但可以看出这段伪码是有缺陷的,完整的反射设置代码会复杂得多。

 

至此,我们拥有了完全对象化而且可配置的模型,这个模型完全可以不用在界面程序(这里用jsp,但可以是其他语言的界面程序文件)中硬编码权限,可以考虑两种整体解决方案:

方案1:仍然在Jsp中写控件代码(这样原有标签可以不改,改后台实现即可),然后把权限标签和权限引用标签独立到另一个xml文件(此时权限引用标签作为权限标签的子标签或者独立标签均可)。

 

方案2:把控件、权限、权限引用全部放到一个xml中进行,jsp退化为模板,好处是可以实现整体式GUI框架,需要跨平台GUI库的话很合适。

 

本概念还有很多需要强化的地方,将在下一阶段(强化)来讲解,敬请关注,如果我不偷懒的话,会尽快补充的。

 

文章刚发时犯了个错误,图片地址是C盘,真是囧,好朋友提醒了我,现在修正了。

友情提示:
信息收集于互联网,如果您发现错误或造成侵权,请及时通知本站更正或删除,具体联系方式见页面底部联系我们,谢谢。

其他相似内容:

热门推荐: