装饰者模式以对客户端透明的方式动态的为对象增加责任此模式提供了一个比继承更为灵活的替代方案来扩展对象的功能避免了继承方法产生的类激增问题而且更方便更改对象的责任 我们经常要为某一些个别的对象增加一些新的职责并不是全部的类例如我们系统留言反馈板块中可能需要过滤用户输入留言中的一些词汇(例如政治敏感词 汇色情词汇等)还可能对用户输入留言进行一些修饰(例如对用户输入的URL自动加上超链接对用户输入的UBB代码进行转换的)还可能将用户输入的 内容定时发送的网管的邮箱中等等如果使用类继承的方式进行设计我们可能要设计一个接口 BodyContentFilterIntf然后在由BodyContentFilterIntf派生出 SensitiveWordContentFilterHtmlContentFilterSendEmailContentFilter等类但是 如果还要要求同时能过滤敏感词汇并能进行修饰或者过滤敏感词汇之后把用户输入的留言发送到网管邮箱等等这样就要增加 SensitiveWordHtmlContentFilterSensitiveWordSendEmaillContentFilter等类这种 方式导致了子类瀑发式的产生 一个灵活的方法是将过滤器嵌入另一个过滤器中由这个过滤器来负责调用被嵌入过滤器的方法并执行自己的 过滤器方法我们称这个嵌入的过滤器为装饰(Decorator)这个装饰与过滤器接口一致装饰将请求向前转到到另一个过滤器并且可能能转发前后执 行一些额外的动作(如修饰发送邮件)透明性使你可以递归的嵌套多个装饰从面可以添加任意多的功能 其实java中 的过滤器模式应用非常多典型的就是IO的Stream操作在IO处理中Java将数据抽象为流(Stream)在IO库中最基本的是 InputStream和OutputStream两个分别处理输出和输入的对象但是在InputStream和OutputStream中之提供了最 简单的流处理方法只能读入/写出字符没有缓沖处理无法处理文件等等 LineNumberInputStreamBufferInputStreamStringBufferInputStream等提供各种不同服务的类只要组合起来就可以实现很多功能如下 FilterInputStream myStream=new LineNumberInputStream ( new BufferInputStream( new StringBufferInputStream( myStringBuffer))); 多个的Decorator被层叠在一起最后得到一个功能强大的流既能够被缓沖又能够得到行数这就是Decorator的威力! 我们定义一个接口BodyContentFilterIntf 来定义所有过滤器要实现的方法 public interface BodyContentFilterIntf { public String filtContent(String aContent) throws ContentFilterException; } 这个接口中只有一个方法filtContent将要过滤的留言传给aContent参数filtContent对aContent进行一些处理(如 装饰URLUBB等)然后将处理后的字符串做为返回值返回如果留言没有通过过滤(如含有敏感词汇等)只要抛出自定义 ContentFilterException异常即可 下面是一个可能的一个过滤器(保证输入的字数多于) public class LengthContentFilter implements BodyContentFilterIntf { private BodyContentFilterIntf bodyContentFilterIntf = null; public HtmlContentFilter(BodyContentFilterIntf aFilter) { bodyContentFilterIntf = aFilter; } public String filtContent(String aContent) throws ContentFilterException { String l_Content = aContent; If (bodyContentFilterIntf!=null) _Content = bodyContentFilterIntf filtContent(l_Content); if (aContentlength()<=) throw new ContentFilterException (输入的字数不能少于!); return aContext; } } 这是另一个过滤器(伪码用来实现向网管邮箱发送邮件) public class SendEmailContentFilter implements BodyContentFilterIntf { private BodyContentFilterIntf bodyContentFilterIntf = null; public SendEmailContentFilter(BodyContentFilterIntf aFilter) { bodyContentFilterIntf = aFilter; } public String filtContent(String aContent) throws ContentFilterException { String l_Content = aContent; if (bodyContentFilterIntf!=null) l_Content = bodyContentFilterIntf filtContent(l_Content); SendEmail(wel_Content) return aContext; } } 当然还有SensitiveWordContextFilter(过滤敏感词汇)HtmlContentFilter(修饰用户输入留言中的超级链接)等 有了这些过滤器我们就可以很方便的为留言版添加各种复合的过滤器例如我们想对输入的留言进行超链接修饰和过滤敏感词汇那么我们只要如下调用即可 try { l_Content = new HtmlContentFilter(new SensitiveWordContextFilter(null)) filtContent(bodyContext); } catch (ContentFilterException ex) { BBSCommonshowMsgInResponse(response exgetMessage()); return; } 我们甚至可以动态的添加不同的过滤器例如对于会员我们要对输入的留言进行超链接修饰并且将他的留言发送到网管邮箱而对于非会员我们则要过滤他输入的敏感词汇并且保证输入的字数不少于我们只要如下调用即可 try { BodyContentFilterIntf bodyContentFilterIntf = null; bodyContentFilterIntf = new HtmlContentFilter(null); if(IsMember==true) bodyContentFilterIntf = new sendEmailContentFilter(bodyContentFilterIntf); else bodyContentFilterIntf = new SensitiveWordContextFilter(bodyContentFilterIntf); l_Content = bodyContentFilterIntffiltContent(bodyContext); } catch (ContentFilterException ex) { BBSCommonshowMsgInResponse(response exgetMessage()); return; } |