最爱Java

书山有路勤为径,学海无涯苦作舟

《AspectJ Cookbook》读书笔记十九: 实现行为型面向对象设计模式

一.实现观察者模式
        观察者模式允许设计者创建对象之间的依赖关系,使得如果一个对象的状态发生变化,则通知另一个对象,并且它可能会产生相应的行动。
package com.aspectj;

import java.util.List;
import java.util.LinkedList;
import java.util.Iterator;

public abstract aspect ObserverPattern 
{
   
protected interface Subject
   
{
      
public void addObserver(Observer observer);
      
public void removeObserver(Observer observer);
   }

   
   
protected interface Observer
   
{
      
public void notifyOfChange(Subject subject);
   }

   
   
private List Subject.observers = new LinkedList();
   
   
public void Subject.addObserver(Observer observer)
   
{
      
this.observers.add(observer);
   }

   
   
public void Subject.removeObserver(Observer observer)
   
{
      
this.observers.remove(observer);
   }

   
   
private synchronized void Subject.notifyObservers()
   
{
      Iterator iter 
= this.observers.iterator();
      
while (iter.hasNext())
      
{
         ((Observer)iter.next()).notifyOfChange(
this);
      }

   }

   
   
protected abstract pointcut subjectChange(Subject s);
   
   after(Subject subject) : subjectChange(subject)
   
{
      subject.notifyObservers();
   }

}


        ObserverPattern方面把Subject和Observer角色定义为标识符,可以通过继承子方面把他们应用于特定的类。通过定义这些角色,ObserverPattern方面就会实现一种机制,当主题改变时,通过该机制来通知观察者。
package com.aspectj;

import com.oreilly.aspectjcookbook.oopatterns.ObserverPattern;

public aspect ConcreteClassAObserver extends ObserverPattern 
{
   declare parents : ConcreteClassB 
implements Subject;

   declare parents : ConcreteClassA 
implements Observer;

   
protected pointcut subjectChange(Subject s) : call(
      
* ConcreteClassB.set*(..))
      
&& target(s);

   
public void ConcreteClassA.notifyOfChange(Subject subject)
   
{
      
this.doSomething(
         
"ConcreteClassA was notified of a change on " + subject);
   }

}
    
    ConcreteClassAObserver把Observer接口应用于ConcreteClassA类,以及把Subject接口应用于ConcreteClassB类。这意味着在ConcreteClassB对象上调用修改器时,将会通知被注册为观察者的ConcreteClassA对象。在notifyOfChange(Subject)方法中声明了在发出通知时,将会调用哪些方法的细节,该方法被添加到ConcreteClassA类中。

二.实现命令模式
        命令设计模式本身支持把请求封装成对象。可以依赖于其目的,把单个或多个操作组合进一个请求。一旦构造了请求对象,就可以从发起对象把它作为单独的实体进行管理。
package com.aspectj;

import java.util.WeakHashMap;

public abstract aspect CommandPattern 
{
   
// Define the Command Pattern interfaces
   
   
// This interface will be fulfilled by all Commands
   public interface Command
   
{
      
      
public void executeCommand(CommandReceiver receiver);
      
      
public boolean isExecutable();
   }

   
   
//    This interface will be fulfilled by all CommandInvokers
   public interface CommandInvoker
   
{
   }

   
   
//    This interface will be fulfilled by all CommandReceivers
   public interface CommandReceiver
   
{
   }

   
   
private WeakHashMap mappingInvokerToCommand = new WeakHashMap();
   
   
public Object setCommand(CommandInvoker invoker, Command command)
   
{
      
return mappingInvokerToCommand.put(invoker, command);
   }

   
   
public Object removeCommand(CommandInvoker invoker)
   
{
      
return setCommand(invoker, null);
   }

   
   
public Command getCommand(CommandInvoker invoker)
   
{
      
return (Command) mappingInvokerToCommand.get(invoker);
   }

   
   
private WeakHashMap mappingCommandToReceiver = new WeakHashMap();
   
   
public Object setReceiver(Command command, CommandReceiver receiver)
   
{
      
return mappingCommandToReceiver.put(command, receiver);
   }

   
   
public CommandReceiver getReceiver(Command command)
   
{
      
return (CommandReceiver) mappingCommandToReceiver.get(command);
   }

   
   
protected abstract pointcut commandTrigger(CommandInvoker invoker);
   
   after(CommandInvoker invoker) : commandTrigger(invoker)
   
{
      Command command 
= getCommand(invoker);
      
if (command != null)
      
{
         CommandReceiver receiver 
= getReceiver(command);
         command.executeCommand(receiver);
      }
 else
      
{
         
// Do nothing: This Invoker has no associated command
      }

   }

   
   
protected pointcut setCommandTrigger(CommandInvoker invoker, Command command);
   
   after(CommandInvoker invoker, Command command) : setCommandTrigger(invoker, command)
   
{
      
if (invoker != null)
         setCommand(invoker, command);
   }

   
   
protected pointcut removeCommandTrigger(CommandInvoker invoker);
   
   after(CommandInvoker invoker) : removeCommandTrigger(invoker)
   
{
      
if (invoker != null)
         removeCommand(invoker);
   }

   
   
public boolean Command.isExecutable()
   
{
      
return true;
   }

}


        CommandPattern抽象方面定义了一些机制,可以通过这些机制来建立CommandInvoker,Command和CommandReceiver的角色,并且让它们彼此交互。
package com.aspectj;

public aspect ConcreteCommand extends CommandPattern 
{
    declare parents : TimedEvent 
implements CommandInvoker;
    declare parents : Printer 
implements CommandReceiver;
    declare parents : VCardPrinter 
implements CommandReceiver;
    declare parents : BusinessCard 
implements Command;

    
public void BusinessCard.executeCommand(CommandReceiver receiver)
    
{
        
if (receiver instanceof Printer)
        
{
            ((Printer) receiver).println(
this.toString());
        }
 else
        
{
            ((VCardPrinter) receiver).printVCard(
this);
        }

    }


    
public void executeCommand(CommandReceiver receiver)
    
{
        ((Printer) receiver).println(
"Command triggered on printer receiver");
    }


    
protected pointcut commandTrigger(CommandInvoker invoker) : call(
        
void TimedEvent.timedOut())
        
&& target(invoker);
}


三.实现迭代器模式
        迭代器模式提供一种机制,通过它将对象集合或聚合的实现与顺序访问集合的机制隔离开。迭代器(或游标)移动对象的聚合移动,从而提供每个对象,同时对聚合的用户隐藏次序和访问实现的细节。
package com.aspectj;

import java.util.Iterator;

public abstract aspect IteratorPattern 
{
   
public interface Aggregate
   
{
      
public Iterator createIterator();
      
      
public Iterator createReverseIterator();
   }

}

        IteratorPattern抽象方面通过定义一个聚合必须实现的接口(这意味着可以迭代任何对象集合),来声明Aggregate(聚合)角色。这个接口包括两个操作:创建正常的迭代器或倒迭代器。
package com.aspectj;

import java.util.Iterator;

public aspect EmployeeIteration extends IteratorPattern 
{
   declare parents : EmployeeCollection 
implements Aggregate;

   
public Iterator EmployeeCollection.createIterator()
   
{
      
return new EmployeeIterator(thistrue);
   }


   
public Iterator EmployeeCollection.createReverseIterator()
   
{
      
return new EmployeeIterator(thisfalse);
   }

}


四.实现调停者模式
        调停者模式通过在调停者角色中提供单点依赖性,将适合同事角色的潜在大量类彼此隔开。扮演调停者角色的类通过提供一个公共点来控制同事启动的不同事件,从而把同事类之间的依赖性减至最小。调停者自身会接受事件,然后封装一个逻辑,用于通知原始事件的合适同事。
package com.aspectj;

import java.util.WeakHashMap;

public abstract aspect MediatorPattern 
{
   
protected interface Colleague
   
{
   }

   
   
protected interface Mediator
   
{
   }

   
   
private WeakHashMap mappingColleagueToMediator = new WeakHashMap();
   
   
private Mediator getMediator(Colleague colleague)
   
{
      Mediator mediator 
=
         (Mediator) mappingColleagueToMediator.get(colleague);
      
return mediator;
   }

   
   
public void setMediator(Colleague c, Mediator m)
   
{
      mappingColleagueToMediator.put(c, m);
   }

   
   
protected abstract pointcut change(Colleague c);
   
   after(Colleague c) : change(c)
   
{
      notifyMediator(c, getMediator(c));
   }

   
   
protected abstract void notifyMediator(Colleague c, Mediator m);
}


        MediatorPattern抽象方面把Colleague和Mediator角色定义为接口,可以通过继承子方面将其用于应用程序特定的类。这个方面定义了mappingColleagueToMediator查寻,可以使用setMediator(Colleague,Mediator)方法操纵它,将同事对象赋予调停者对象。
        MediatorPattern方面提供了由于方面实现的change(..)抽象切入点,在同事发生变化时,这个切入点通过调用notifyMediator(Colleague,Mediator)方法来触发调停者上的通知。
package com.aspectj;

public aspect DialogMediator extends MediatorPattern 
{
   declare parents : ListBox 
implements Colleague;
   declare parents : EntryField 
implements Mediator;
   
   
protected pointcut change(Colleague c) : (
         execution(
void ListBox.setSelection(..)) && this(c));
   
   
protected void notifyMediator(Colleague c, Mediator m)
   
{
      ListBox listBox 
= (ListBox) c;
      EntryField entryField 
= (EntryField) m;
      entryField.setText(listBox.getSelection());
   }

}


五.实现责任链模式
        责任链模式允许把请求的来源与决定应该使用哪个处理程序来处理请求隔离开,这个处理程序是从潜在的大量针对请求的处理程序中选择的。代表连角色的类把请求从其来源,沿着处理程序列表,一直导向一个处理程序,它会接受请求并处理它。
package com.aspectj;

import java.util.WeakHashMap;

public abstract aspect ChainOfResponsibilityPattern 
{
   
protected interface Handler
   
{
   }

   
   
private WeakHashMap successors = new WeakHashMap();
   
   
protected void receiveRequest(Handler handler, Object request)
   
{
      
if (handler.acceptRequest(request))
      
{
         handler.handleRequest(request);
      }
 else
      
{
         
// The handler will not accept the request
         Handler successor = getSuccessor(handler);
         
if (successor == null)
         
{
            
// Last handler in the chain so must deal with the request
            
// This is a rudimentary implementation and more complex
            
// logic could be applied here or perhaps in the concrete
            
// aspects that extend this abstract one
            handler.handleRequest(request);
         }
 else
         
{
            
// Hand the request on to the next successor in the chain
            receiveRequest(successor, request);
         }

      }

   }

   
   
public boolean Handler.acceptRequest(Object request)
   
{
      
// The default as defined here is to reject the request
      
// This is implemented by the application specific
      
// concrete aspects
      return false;
   }

   
   
public void Handler.handleRequest(Object request)
   
{
      
// A default empty implementation that is overridden
      
// if required by the application specific concrete aspects
   }

   
   
protected abstract pointcut eventTrigger(Handler handler, Object request);
   
   after(Handler handler, Object request) : eventTrigger(handler, request)
   
{
      receiveRequest(handler, request);
   }

   
   
public void setSuccessor(Handler handler, Handler successor)
   
{
      successors.put(handler, successor);
   }

   
   
public Handler getSuccessor(Handler handler)
   
{
      
return ((Handler) successors.get(handler));
   }

}

        ChainOfResponsibilityPattern抽象方面定义了Handler接口,然后可通过特殊化的子方面将其应用于参与链中的特定应用程序内的所有类。方面维护链,并询问将如何通过特定子方面处理请求的细节。
package com.aspectj;

public aspect HelpChain extends ChainOfResponsibilityPattern 
{
   declare parents : PrintButton 
implements Handler;
   declare parents : PrintDialog 
implements Handler;
   declare parents : Manager 
implements Handler;
   
   
protected pointcut eventTrigger(Handler handler, Object event) : call(
         
void PrintButton.doClick(..))
         
&& target(handler)
         
&& args(event);
   
   
// We introduce the attributes purely to give the handlers a means of
   
// deciding if they have already handled a request or not
   
// If they have then they are allowed to refuse the request in this
   
// example.
   
// In a real application these would not be required.
   private boolean Handler.alreadyHandledRequest = false;
   
   
public boolean Handler.acceptRequest(Object event)
   
{
      
return !this.alreadyHandledRequest;
   }

   
   
public void PrintButton.handleRequest(Object event)
   
{
      
if (!this.acceptRequest(event))
      
{
         System.out.println(
         
"PrintButton Forced to handle Request due to being last in the chain (Implementation Decision)");
      }

      System.out.println(
"PrintButton handling request: " + event);
      
this.alreadyHandledRequest = true;
   }

   
   
public void PrintDialog.handleRequest(Object event)
   
{
      
if (!this.acceptRequest(event))
      
{
         System.out.println(
         
"PrintDialog Forced to handle Request due to being last in the chain (Implementation Decision)");
      }

      System.out.println(
"PrintDialog handling request: " + event);
      
this.alreadyHandledRequest = true;
   }

   
   
public void Manager.handleRequest(Object event)
   
{
      
if (!this.acceptRequest(event))
      
{
         System.out.println(
         
"Manager Forced to handle Request due to being last in the chain (Implementation Decision)");
      }

      System.out.println(
"Manager handling request: " + event);
      
      
this.alreadyHandledRequest = true;
   }

}



六.实现备忘录模式
        备忘录模式提供了一种机制,通过这种机制,可以在以后的某个时间恢复对象的原始状态,而无需把准确的机制与要回滚状态的对象耦合起来。备忘录封装了在以后某个时间恢复对象的先前内部状态所需的全部信息。这种能力可以用于提供某种形式的撤销特性,以恢复特定应用程序内对象的状态。
package com.aspectj;

public abstract aspect MementoPattern 
{
   
public interface Memento
   
{
      
public void setState(Originator originator);
      
public Object getState();
   }

   
   
public interface Originator
   
{
      
public void setMemento(Memento memento);
      
public Memento createMemento();
      
public Object getState();
   }

}

        EmployeeMementor指定Employee类是一个发起者,从而支持创建其状态的备忘录.createMemento()方法允许客户获得Employee对象的备忘录;setMemento(Memento)方法将把Employee对象恢复到备忘录中存储的状态,当创建备忘录以访问和恢复Employee发起者对象时将使用getState()方法。
package com.aspectj;

public aspect EmployeeMemento extends MementoPattern 
{
   declare parents : Employee 
implements Originator;

   
public void Employee.setMemento(Memento memento)
   
{
      Object object 
= memento.getState();
      Employee stateToRestore 
= (Employee) object;
      
this.setName(stateToRestore.getName());
      
this.setSalary(stateToRestore.getSalary());
   }


   
public Memento Employee.createMemento()
   
{
      Memento memento 
= new DefaultMemento();
      memento.setState(
this);
      
return memento;
   }


   
public Object Employee.getState() throws MementoException
   
{
      Employee employee 
= new Employee(this.getName(), this.getSalary());
      
return employee;
   }

}




七.实现策略模式
        策略模式用于把客户类和特定算法或策略的实际实现细节隔离开,传统上,实现策略的所有单独的类都会实现一个不同的接口,允许把客户与不同的实现分开。
package com.aspectj;

import java.util.Hashtable;

public abstract aspect StrategyPattern 
{
   Hashtable strategyPerContext 
= new Hashtable();
   
   
protected interface Strategy
   
{
   }

   
   
protected interface Context
   
{
   }

   
   
public void setConcreteStrategy(Context c, Strategy s)
   
{
      strategyPerContext.put(c, s);
   }

   
   
public Strategy getConcreteStrategy(Context c)
   
{
      
return (Strategy) strategyPerContext.get(c);
   }

}


        StrategyPattern抽象方面将Strategy和Context角色定义为接口。使用一个散列表来查询要使用的特定的具体策略。
package com.aspectj;

public aspect SortingStrategy extends StrategyPattern 
{
   declare parents : Sorter 
implements Context;
   declare parents : LinearSorter 
implements Strategy;
   declare parents : BubbleSorter 
implements Strategy;
   
   
int[] around(Sorter s, int[] numbers) : call(int[] Sorter.sort(int[]))
      
&& target(s)
      
&& args(numbers)
   
{
      Strategy strategy 
= getConcreteStrategy(s);
      
if (strategy instanceof BubbleSorter)
         ((BubbleSorter) strategy).sort(numbers);
      
else if (strategy instanceof LinearSorter)
         ((LinearSorter) strategy).sort(numbers);
      
return numbers;
   }

}


        SortingStrategy方面为待排序的特定环境声明了两种不同的排序策略。将执行的实际策略依赖与运行时为特定环境声明的策略类型。
八.实现访问者模式
        访问者模式封装了一个请求,当在整个结构中传递它时,可以通过对象的层次结构来执行它。
package com.aspectj;

public abstract aspect VisitorPattern 
{
   
public interface Element
   
{
      
public void accept(Visitor visitor);
   }

   
   
public interface CompositeElement extends Element
   
{
      
public Element[] getElements();
   }

   
   
public interface Result
   
{
   }

   
   
public interface Visitor
   
{
      
public void visitElement(Element element);
      
      
public void visitComposite(CompositeElement element);
      
      
public Result getResult();
   }

   
   
public void CompositeElement.accept(Visitor visitor)
   
{
      visitor.visitComposite(
this);
   }

   
   
public void Element.accept(Visitor visitor)
   
{
      visitor.visitElement(
this);
   }

}

        VisitorPattrn抽象方面把CompositeElement和Element角色定义为待访问的对象结构的一部分。Visitor角色描述了如何通知Visitor它正在访问哪种元素。这个角色应用于可能传递到结构不同部分的对象,他们是复合元素或简单元素。然后扩展CompositeElement和Element角色,以提供用于传递Visitor的方法。
package com.aspectj;

public aspect InventoryVisitor extends VisitorPattern 
{
    declare parents : FloppyDisk 
implements Element;

    declare parents : HardDisk 
implements Element;
    
    declare parents : Processor 
implements Element;

    declare parents : Computer 
implements CompositeElement;

    declare parents : Motherboard 
implements CompositeElement;

    declare parents : InventoryReport 
implements Result;

    
public Element[] Computer.getElements()
    
{
        Element[] elements 
= new Element[3];
        elements[
0= this.getMotherboard();
        elements[
1= this.getHardDisk();
        elements[
2= this.getFloppyDisk();
        
return elements;
    }


    
public Element[] Motherboard.getElements()
    
{
        Element[] elements 
= new Element[1];
        elements[
0= this.getProcessor();
        
return elements;
    }


}


九.实现模板方法模式
    模板方法模式可以利用它来声明通用工作流内的抽象方法。
package com.aspectj;

public interface AlgorithmDefinition
{
   
public String runAlgorithm();

   
public StringBuffer stepOne();

   
public void stepTwo(StringBuffer data);

   
public void stepThree(StringBuffer data);

   
public String stepFour(StringBuffer data);
}


package com.aspectj;

public aspect DefaultAlgorithmImplementation 
{    
   
public String AlgorithmDefinition.runAlgorithm()
   
{
      StringBuffer dataInProcess 
= this.stepOne();
      
this.stepTwo(dataInProcess);
      
this.stepThree(dataInProcess);
      
return this.stepFour(dataInProcess);
   }

   
   
public StringBuffer AlgorithmDefinition.stepOne()
   
{
      
return new StringBuffer();
   }

   
   
public String AlgorithmDefinition.stepFour(StringBuffer data)
   
{
      
return data.toString();
   }

}

        DefaultAlgorithmImplementation方面指定了算法执行步骤的顺序,以及几个步骤的默认实现。通过使用面向方面技术,可以在接口而不是抽象类中声明算法模板。然后,依靠静态横切技术,可以在具体的方面中指定合适的通用步骤的默认实现,包括以正确顺序调用步骤的方法。可以通过实现算法接口的类来完成更特定的步骤,从而在合适的地方自动获得默认的行为。
        这种模式的面向方面实现的优点是:它通过把部分抽象实现移到方面中并使用静态横切方法来提供默认在接口上的部分实现,消除了模式中的顶级类必须在抽象类中的限制。
十.实现状态模式
        状态模式提供了一种机制,这种机制,可以基于对象的状态来改变它的行为。状态被封装在它自己的对象中,这个对象然后又被调用对象说包含。调用对象把受其状态影响的所有方法请求传递给状态对象,状态对象则基于此刻它的类来改变响应。
package com.aspectj;

public aspect TCPConnectionState 
{
   
protected TCPState listening = new TCPListen();

   
protected TCPState acknowledged = new TCPAcknowledged();

   
protected TCPState closed = new TCPClosed();

   after(TCPConnection connection) : initialization(
new ())
      
&& target(connection)
   
{
      listening.setConnection(
new SocketConnection());
      connection.setState(listening);
   }


   after(TCPConnection connection, TCPState state) : call(
      
void TCPState +.acknowledge())
      
&& target(state)
      
&& this(connection)
   
{
      
if (connection.getState() == listening)
      
{
         acknowledged.setConnection(listening.getConnection());
         connection.setState(acknowledged);
      }

   }


   after(TCPConnection connection, TCPState state) : call(
      
void TCPState +.close())
      
&& target(state)
      
&& this(connection)
   
{
      
if ((connection.getState() == listening)
         
|| (connection.getState() == acknowledged))
      
{
         connection.setState(closed);
      }

   }

}

        TCPConnectionState方面指定:TCPConnectionState类状态将在创建时被侦听,在调用acknowledge()方法时被确认,以及在调用close()调用时被关闭。它还指定:如果依赖于这些方法的顺序调用它们,则会发生什么。无需影响TCPConnection类,既可完成所有这些操作。
十一.实现外观模式和解释器模式
        上述两种模式使用面向方面方法无法获得任何设计或实现上的好处。

posted on 2008-08-29 10:04 Brian 阅读(304) 评论(0)  编辑  收藏 所属分类: 《AspectJ Cookbook》读书笔记


只有注册用户登录后才能发表评论。


网站导航:
 

公告


导航

<2008年8月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
31123456

统计

常用链接

留言簿(4)

随笔分类

随笔档案

收藏夹

搜索

最新评论

阅读排行榜

评论排行榜