分享
 
 
 

AspectJ实现设计模式(七)—装饰模式

王朝java/jsp·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

本文介绍使用AspectJ实现设计模式之装饰模式,文章利用一个打印发票的例子说明如何使用AspectJ来实现装饰模式。

示例说明

装饰模式是大家都很熟悉的一个模式,最典型的例子就是Java的I/O库,它的设计完全按照装饰模式。我们通常在客户端使用new操作符来对一个类进行包装,例如下述代码

DataOutputStream out=new DataOutputStream(new FileOutputStream(“1.txt”));

它使用DataOutputStream来包装FileOutputStream,所以可以使用前者的方法来对文件流进行写入。而采用AspectJ实现的装饰模式中,在客户端我们将不在看见这样的new操作,而是直接将装饰行为织入方法执行内部,在方法内部增加额外的操作。现将<<Java与模式>>一书中有打印发票的例子改用AspectJ实现,我们看看到底AspectJ是如何将额外操作织入方法体中的。系统UML图如下所式

源代码

抽象方面OrderDecorator.java

abstract aspect OrderDecorator {

declare parents : SalesOrder extends Order;

public void SalesOrder.print(){

super.print();

}

protected pointcut print(Order order) : target(order) && call(public void print());

}

抽象方面利用类型间声明为SalesOrder类声明了父类,并实现了方法print()。同时还定义了一个切点print(Order order),它将捕捉Order类print方法调用。

具体方面HeaderDecorator.java

public aspect HeaderDecorator extends OrderDecorator{

void around(Order order) : print(order){

printHeader(order);

proceed(order);

}

private void printHeader(Order order){

System.out.println("\t***\tINVOICE\t***");

System.out.println("XYZ Incorporated\nDate of Sale:");

System.out.println(order.getSalesDate());

System.out.println("======================================");

System.out.println("Item\t\tUnits\tUnit Price\tSubtotal");

}

}

HeaderDecorator方面实现发票头打印功能,它定义了通知around截获切点print所捕捉的方法调用,然后先打印发票头再利用proceed()方法执行所捕捉到的方法的原有逻辑。

具体方面FooterDecorator.java

public aspect FooterDecorator extends OrderDecorator{

declare precedence : FooterDecorator,HeaderDecorator; //声明优先顺序

void around(Order order) : print(order){

proceed(order);

printFooter(order);

}

private void printFooter(Order order){

System.out.println("=====================================");

System.out.println("Total\t\t\t\t"+order.formatCurrency(order.getGrandTotal()));

}

}

FooterDecorator方面实现发票注脚打印功能,它定义了通知around截获切点print所捕捉的方法调用,然后先利用proceed()方法执行所捕捉到的方法的原有逻辑再打印注脚信息。还有最重要的一点是它的precedence声明,这个声明决定了FooterDecorator方面和HeaderDecorator方面捕捉同一个方法调用时同一通知的执行顺序。方面中的声明说明HeaderDecorator比FooterDecorator的优先级别高,其通知较先执行。

抽象定单类Order.java

import java.util.*;

import java.text.NumberFormat;

abstract public class Order {

private OrderLine InkOrderLine;

protected Collection items=new ArrayList();

protected String customerName;

protected Date salesDate;

public void print(){

Iterator it=items.iterator();

while(it.hasNext()){

OrderLine item=(OrderLine)it.next();

item.printLine();

}

}

public String getCustomerName(){

return customerName;

}

public void setCustomerName(String customerName){

this.customerName=customerName;

}

public Date getSalesDate(){

return salesDate;

}

public void setSalesDate(Date salesDate){

this.salesDate=salesDate;

}

public void addItem(OrderLine item){

items.add(item);

}

public void removeItem(OrderLine item){

items.remove(item);

}

public double getGrandTotal(){

double amount=0.0D;

Iterator it=items.iterator();

while(it.hasNext()){

OrderLine item=(OrderLine)it.next();

amount+=item.getSubTotal();

}

return amount;

}

public String formatCurrency(double amount){

return NumberFormat.getCurrencyInstance().format(amount);

}

}

定单条目类OrderLine.java

import java.text.NumberFormat;

public class OrderLine {

private String itemName;

private int units;

private double unitPrice;

public String getItemName(){

return itemName;

}

public void setItemName(String itemName){

this.itemName=itemName;

}

public int getUnits(){

return units;

}

public void setUnits(int units){

this.units=units;

}

public double getUnitPrice(){

return unitPrice;

}

public void setUnitPrice(double unitPrice){

this.unitPrice=unitPrice;

}

public void printLine(){

System.out.println(itemName+"\t"+units+"\t"

+formatCurrency(unitPrice)+"\t"

+formatCurrency(getSubTotal()));

}

public double getSubTotal(){

return units*unitPrice;

}

private String formatCurrency(double amount){

return NumberFormat.getCurrencyInstance().format(amount);

}

}

具体销售定单类SalesOrder.java

public class SalesOrder {}

客户端演示Demo.java

public class Demo {

private static Order order;

public static void main(String [] args){

order=new SalesOrder();

order.setSalesDate(new java.util.Date());

order.setCustomerName("starchu1981");

OrderLine item1=new OrderLine();

item1.setItemName("Fire Wheel Tire");

item1.setUnitPrice(154.23);

item1.setUnits(4);

order.addItem(item1);

OrderLine item2=new OrderLine();

item2.setItemName("Front Fender");

item2.setUnitPrice(300.45);

item2.setUnits(1);

order.addItem(item2);

order.print(); //这里与Java版本的客户端代码不同,稍后解释。

}

}

结果分析

Demo输出的结果如下

*** INVOICE ***

XYZ Incorporated

Date of Sale:

Thu Jul 24 11:45:10 CST 2003

=================================

Item Units Unit Price Subtotal

Fire Wheel Tire 4 ¥154.23 ¥616.92

Front Fender 1 ¥300.45 ¥300.45

=================================

Total ¥917.37

例子输出与我们期望的结果是一致的。特别值得注意的是代码的最后一行,通常在Java中可能会有下面的代码

Order order=new HeaderDecorator(new FooterDecorator());

order.print();

而使用AspectJ构造的装饰模式在客户端完全将装饰现象消除,可以直接使用方法,而不需要向在Java中那样提供具体装饰类的构造行为,这使得客户端代码更加透明,客户可以完全不知道装饰类的存在。当然这样做也有一个缺点,就是客户端无法自己控制所有的装饰行为,例如如果客户无法撤消打印注脚行的行为。

本文由starchu1981保留版权,如果需要转贴请写明作者和出处。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有