技术开发 频道

用AspectJ增强设计模式下

IT168 技术文档】

    在这篇文章的第1 部分中,我从面向方面的角度研究了两个广泛应用的面向对象设计模式。在演示了适配器和修饰器模式在 Java 系统和 AspectJ 系统中的实现方式之后,我从代码理解、重用、维护性和易于组合几方面考虑了每种实现的效果。在两种情况下,我发现横切 Java 实现模块性的模式在 AspectJ 实现中可以组合到单独的一个方面中。理论上,这种相关代码的协同定位可以使模式变得更易理解、更改和应用。用这种方式看模式,就转变对 AOP 的一个常见批评 —— 阻止开发人员通过阅读代码了解代码的行为。在这篇文章的第 2 部分中,我将通过深入研究观察者(Observer)模式,完成我对 Java 语言的模式实现和 AspectJ 模式实现的比较。

    我选择把重点放在观察者(Observer)模式上,因为它是OO设计模式的皇后。该模式被人们广泛应用(特别是在 GUI 应用程序中),并构成了 MVC 架构的关键部分。它处理复杂的问题,而在解决这类问题方面表现得相对较好。但是,从实现需要的努力和代码理解的角度来说,它还是带来了一些难以解决的难题。与修饰器或适配器模式不同(它们的参与者主要是为模式新创建的类),观察者(Observer)模式要求您先侵入系统中现有的类,然后才能支持该模式 —— 至少在 Java 语言中是这样。

    方面可以降低像观察者(Observer)模式这种侵入性模式的负担,使得模式参与者更灵活,因为不需要包含模式代码。而且,模式本身可以变成抽象的基本方面,允许开发人员通过导入和应用它来实现重用,不必每次都要重新考虑模式。为了查看这些可能性如何发挥作用,我将继续本文第一部分设置的格式。我将从示例问题开始,提供对观察者(Observer)模式的通用描述。然后我将描述如何用 AspectJ 和 Java 语言实现观察者(Observer)模式。在每个实现之后,我将讨论是什么造成模式的横切,模式的这个版本在理解、维护、重用和组合代码方面有什么效果。

    在继续后面的讨论之前,请单击本页顶部或底部的 代码 图标,下载本文的源代码。

    观察者(Observer)模式

    根据 Portland Pattern Repository Wiki(请参阅 参考资料 一节,获得有关的细节),观察者(Observer)模式的用途是定义对象之间的一对多依赖关系,因此,当一个对象的状态发生改变时,其所有依赖项都会得到通知,并自动更新。这使得观察者适用于所有类型的通知需要。请考虑以下情况:


    关于本系列

    AOP@Work 系列是为具有一定面向方面的编程背景、并准备扩展或者加深其知识的开发人员准备的。与大多数developerWorks 文章一样,本系列具有很高实用性:从每一篇文章中学到的知识立刻就能使用得上。

    所挑选的为这个系列撰稿的每一位作者,都在面向方面编程方面处于领导地位或者拥有这方面的专业知识。许多作者都是本系列中讨论的项目或者工具的开发人员。每篇文章都经过仔细审查,以确保所表达的观点的公平和准确。

    关于文章的意见和问题,请直接与文章的作者联系。如果对整个系列有意见,可以与本系列的组织者 Nicholas Lesiecki 联系。更多关于 AOP 的背景知识,请参阅 参考资料。

    条形图可以观察它显示的数据对象,以便在这些对象变化时对它们进行重新绘制。

    AccountManager 对象能够观察 Account,这样,在帐户状态改变时,它们可以向销售人员发送一封电子邮件。

    支付服务能够观察在线音乐商店中的歌曲播放事件,以便向客户收费。

    我将把重点放在最后一个场景上,将它作为这篇文章的示例。(这种针对问题域的想法是从 “在 .NET 中实现观察者”中借鉴的;有关的细节,请参阅 参考资料 一节。)假设您要向在线音乐商店添加一些特性。商店已经拥有逐个播放 Songs 的能力,还有把它们组合成在线 Playlists 的能力。客户还可以查看指定歌曲的歌词。现在需要添加收费和统计功能。首先,系统应当跟踪播放和歌词显示事件,以便对客户进行适当的收费。第二,系统该当更新播放最频繁的歌曲列表,用来在“最流行”部分显示。清单 1 包含系统中已经存在的核心对象的代码:

    清单 1. 在线音乐服务的核心领域对象

//common interface for items that //can be played public interface Playable { String getName(); void play(); } public class Song implements Playable{ private String name; public Song(String name) { this.name = name; } public String getName() { return name; } public void play() { System.out.println("Playing song " + getName()); } public void showLyrics(){ System.out.println("Displaying lyrics for " + getName()); } } public class Playlist implements Playable { private String name; private List songs = new ArrayList(); public Playlist(String name) { this.name = name; } public void setSongs(List songs) { this.songs = songs; } public void play() { System.out.println("playing album " + getName()); for (Song song : songs) { song.play(); } } public String getName() { return name; } } public class BillingService{ public void generateChargeFor(Playable playable) { System.out.println("generating charge for : " + playable.getName()); } } public class SongPlayCounter { public void incrementPlays(Song s){ System.out.println("Incrementing plays for " + s.getName()); } }

    现在已经看到了核心系统,让我们来考虑一下 AOP 之前的观察者实现。

0
相关文章