设计模式--装饰者模式
现在在做贵州南明的绩效考核系统,遇到这样一个需求:
现在需要做个下了数据列表,里面取考核方案。现在这个考核方案数据集合,有权限限制。现在数据库表结构是这么设计的。
有一张考核方案主表,里面描述了考核方案的基本信息,比如考核方案编号,方案名称等等。
还有2张权限控制表,一张是方案机构表,此表描述了机构下的方案集合。一张是方案角色表,描述了方案于角色的关系。
现在的权限是,我需要根据登陆者的登陆机构,和他的角色,分别查找方案机构表,和方案角色表,把两张表的方案去重复形成一个方案数据集合。
这样问题也来了,如果现在系统要扩展,方案的权限增加,比如,要求方案和岗位要挂钩。那我们又当如何。当然,这样的需求,数据库方面,在增加个方案岗位关系表就可以满足需求,关键是,我们程序又当如何去适应这样的变化。
按照现在的做法,又得把相关代码拿出来修改,有的甚至要改很多地方。
对这样的需求,我们先看看用继承是怎么去适应这样的需求:
现在方案集合只更机构和角色相关联:
public class A { private int bankcd;//机构 private String roleid;//角色 public List getSchemeList() { //这里面就是实现用 bankcd 和 roleid 去方案的代码 } }
现在需求变化,要求把岗位增加进去,数据库岗位方案表建好了,程序的变化用继承来
public Class B extends A { private String workid;//增加了岗位 //overwirte 重写超类方法 public List getSchemeList() { List list01=super.getSchemeList(); List list02=......//这里通过使用workid取方案集合 List listsum......这里listsum合并list01和list02的方案 return listsum; } }
以此类推,如果在增加权限,Class C 再继承 B,再重写getSchemeList的方法
这样做的问题再于:
在这条继承链上,A<--B<--C 顺序是不能随便更改,比如我现在不需要B了,也就是我不要岗位权限了,这就不好去掉,取掉B ,C必然会受到影响。
这里我想到了设计模式的装饰着模式,它很很好的实现上面那种继承功能,但比继承更加灵活。
它的原理好比,在礼物外面,加包装纸,可以加一张,再加一张,顺序也是可以很好变化,去掉一层包装也很容易。
现在的做法:把Class a 的需要被重载的方法getSchemeList()抽像成一个接口,现在被包装着者是Class A,包装者分别有Class B ,和Class C,他们都实现相同的接口。为什么装饰者和被装饰者要继承于同一个基类或实现同一个接口,原因是应为要保证包装者和被包装者的类型要一致。这就好比一颗糖,外面包层糖纸,还是糖的道理是一样的。同过这样方式去实现这样的需求,要易于扩展点。
下面是具体做法:
顶端接口 SchemeInter
public interface SchemeInter { /** * 更具权限获取方案集合 * @param map * @return */ public List getSchemeList(Map map); }
具体的被包装组件为SchemeInterImp
public class SchemeInterImp implements SchemeInter { public List getSchemeList(Map map) { // TODO Auto-generated method stub //现在实现的是更具机构和角色取方案集合 List list=new ArrayList(); AssMainService service=(AssMainService)SpringUtil.getBean("assMainService"); list=service.createProgList(map); return list; } }
3.包装者抽象类SchemeDecorater
public abstract class SchemeDecorater implements SchemeInter { //根据权限取方案集合 public abstract List getSchemeList(Map map); }
4.具体建了一个更时间类型有关的包装者 SchemeDecoratorTime
public class SchemeDecoratorTime extends SchemeDecorater { private SchemeInter schemeinter;//每个装饰者都有一个被装饰对象 public SchemeDecoratorTime(SchemeInter schemeinter) { this.schemeinter=schemeinter; } @Override public List getSchemeList(Map map) { // TODO Auto-generated method stub List list=new ArrayList(); List suplist=schemeinter.getSchemeList(map); //合并超类集合和现在加上时间段的数据结合 list=suplist; return list; } }
5.具体调用代码
//用装饰者模式实现数据的获取 List list=new ArrayList(); SchemeInter wrapedobj=new SchemeInterImp();//实例化一个被包装对象 wrapedobj=new SchemeDecoratorTime(wrapedobj);//形成第一成包装 //在下面增加其它包装 wrapedobj=new SchemeDecoratorOther(wrapedobj);//第2成包装 ....................................... // list=wrapedobj.getSchemeList(map);