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

原创 2003年07月25日 08:13:00

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

 

示例说明

       装饰模式是大家都很熟悉的一个模式,最典型的例子就是JavaI/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),它将捕捉Orderprint方法调用。

 

具体方面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方面捕捉同一个方法调用时同一通知的执行顺序。方面中的声明说明HeaderDecoratorFooterDecorator的优先级别高,其通知较先执行。

 

抽象定单类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保留版权,如果需要转贴请写明作者和出处。

 

Android设计模式之一个例子让你彻底明白装饰者模式(Decorator Pattern)

导读这篇文章中我不会使用概念性文字来说明装饰者模式,因为通常概念性的问题都很抽象,很难懂,使得读者很难明白到底为什么要使用这种设计模式,我们设计模式的诞生,肯定是前辈们在设计程序的时候遇到了某种困难,...
  • nugongahou110
  • nugongahou110
  • 2015年12月27日 19:40
  • 2971

设计模式——装饰模式(Decorator)

要想正确理解设计模式,首先必须明确它是为了解决什么问题而提出来的。 设计模式学习笔记 ——Shulin 转载请注明出处:http://blog.csdn.net/zhshulin 1、概念 ...
  • u012909091
  • u012909091
  • 2014年08月18日 20:23
  • 18603

设计模式-装饰者模式(Go语言描述)

什么是装饰者模式好久没有更新设计模式系列的博客了, 今天我们来聊一聊装饰者模式, 用过java的同学肯定对装饰者模式非常熟悉,就算你不知道什么是装饰者模式这概念, 你也一定在代码中经常用到这个模式,为...
  • qibin0506
  • qibin0506
  • 2016年04月07日 08:55
  • 5368

调侃《HeadFirst设计模式》之装饰者模式

今天让我们继续跟随《Head First 设计模式》的足迹,聊一个新的设计模式,有了它,你将能够在不修改任何底层代码的情况下,给你的(或别人的)对象赋予新的职责。首先,按照惯例,从故事说起——    ...
  • sinat_23092639
  • sinat_23092639
  • 2015年04月05日 10:52
  • 870

简单Java代码实例助你通俗易懂的理解什么是装饰(者)设计模式 (Decorator)

首先抛开到处都有的文字概念。来看下面的例子。 现在以:人吃饭。这个需求为例。来讲解这个设计模式。 1.0:想当年,人们都比较朴实。吃饭就是简简单单的吃饭。 那么PersonBefore类里面一个简单的...
  • qq_27093465
  • qq_27093465
  • 2016年11月24日 15:34
  • 1014

设计模式-装饰模式(理解)

看了《大话设计模式》pdf版的装饰模式和其他博客上的一些讲解,第一遍很难get到讲解的点在哪。经国深思,记录下深思的结果。 装饰模式,其实就是用递归的方式实现了面向切面(接口)编程。面向切面...
  • Scalaaaaaa
  • Scalaaaaaa
  • 2016年07月12日 15:22
  • 259

各个设计模式的优缺点

设计原则 1、找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。 2、针对接口编程(实际上是针对超类编程),而不是针对实现编程。 策略模式(Strategy Patter...
  • w302974215
  • w302974215
  • 2015年11月02日 14:04
  • 2827

设计模式练习(9)——装饰模式

装饰模式 一、题目:简单的手机(SimplePhone)在接收到来电的时候,会发出声音来提醒主人,而现在我们需要为该手机添加一项功能,在接收来电的时候,除了有声音,还能产生震动(JarPhone),还...
  • qq_33220449
  • qq_33220449
  • 2017年01月20日 15:30
  • 783

设计模式学习之装饰模式:IO流的装饰器

IO流的装饰器 题目分析:通过对java的io系列类分析得知,java的io流使用了设计模式中的装饰模式,以动态的给一个对象增加职责,能够更加灵活的增加功能。通过看io的源代码得知FilterOut...
  • u014293306
  • u014293306
  • 2015年06月23日 14:07
  • 1415

23种设计模式-17-装饰模式

目录(?)[-] 一装饰模式简介Brief Introduction二解决的问题What To Solve三装饰模式分析Analysis 装饰模式结构源代码程序运行结果 四案例分析Exa...
  • a925907195
  • a925907195
  • 2014年12月15日 20:10
  • 379
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:AspectJ实现设计模式(七)—装饰模式
举报原因:
原因补充:

(最多只允许输入30个字)