最爱Java

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

《AspectJ Cookbook》读书笔记十八: 实现结构型面向对象设计模式

一.实现复合模式
        复合模式能够把集合中的对象组合在一起,并且以某种方式与整个组交互,这种交互式类似于同组中的单个成员进行交互。
package com.aspectj;

import java.util.Enumeration;
import java.util.Vector;
import java.util.WeakHashMap;

public abstract aspect CompositePattern {
    
public interface Component{}
    
    
protected interface Composite extends Component{}
    
    
protected interface Leaf extends Component{}
    
    
private WeakHashMap perComponentChildren = new WeakHashMap();
    
    
private Vector getChildren(Component s) {
        Vector children 
= (Vector) perComponentChildren.get(s);
        
if (children == null{
            children 
= new Vector();
            perComponentChildren.put(s, children);
        }

        
return children;
    }

    
    
public void addChild(Composite composite , Component component) {
        getChildren(composite).add(component);
    }

    
    
public void removeChild(Composite composite , Component component) {
        getChildren(composite).remove(component);
    }

    
    
public Enumeration getAllChildren(Component c) {
        
return getChildren(c).elements();
    }

    
    
public interface Visitor {
        
public void doOperation(Component c);
    }

    
    
public void recurseOperation(Component c , Visitor v) {
        
for (Enumeration enums = getAllChildren(c) ; enums.hasMoreElements();) {
            Component child 
= (Component) enums.nextElement();
            v.doOperation(child);
        }

    }

    
    
public interface FunctionVisitor {
        
public Object doFunction(Component c);
    }

    
    
public Enumeration recurseFunction(Component c , FunctionVisitor fv) {
        Vector results 
= new Vector();
        
for (Enumeration enums = getAllChildren(c) ; enums.hasMoreElements();){
            Component child 
= (Component) enums.nextElement();
            results.add(fv.doFunction(child));
        }

        
return results.elements();
    }

}


package com.aspectj;

import java.io.PrintStream;

public aspect GraphicComposite extends CompositePattern {
    declare parents:Window 
implements Composite;
    declare parents:Line 
implements Leaf;
    declare parents:Rectangle 
implements Leaf;

    
public void Component.draw(PrintStream s) {
        s.println(
"Drawing:" + this);
    }

    
    
public void Composite.draw(final PrintStream s) {
        s.println(
"Composite:" + this);
        GraphicComposite.aspectOf().recurseOperation(
this , new Visitor(){
            
public void doOperation(Component c){
                c.draw(s);
            }

        }
);
    }

    
    
public void Leaf.draw(PrintStream s) {
        s.println(
"Drawing Leaf: " + this);
    }

}


二.实现享元模式
        享元模式提供了一些机制,利用这些机制通过在合适的地方共享对象,可以把细粒度的对象纳入到OO设计中,而不会带来资源和性能损失。重型对象潜在地通过许多享元对象来封装要引用的实际数据。

package com.aspectj;

import java.util.Hashtable;

public abstract aspect FlyweightPattern 
{
   
private Hashtable flyweightPool = new Hashtable();

   
public interface Flyweight
   
{
   }

   
   
protected abstract pointcut flyweightCreation(Object key);
   
   Object around(Object key) : flyweightCreation(key) 
&& !within(com.oreilly.aspectjcookbook.oopatterns.FlyweightPattern+)
   
{
      
return this.checkFlyweight(key);
   }

   
   
/**
    * Applies the flyweight checking policy.
    * 
    * 
@param key
    *           The key that determines whether a new flyweight should be
    *           created or not
    * 
@return The new object that could be a flyweight or a new instance.
    
*/

   
public synchronized Flyweight checkFlyweight(Object key)
   
{
      
if (flyweightPool.containsKey(key))
      
{
        
return (Flyweight) flyweightPool.get(key);
      }

      
else
      
{
        Flyweight flyweight 
= createNewFlyweight(key);
        flyweightPool.put(key, flyweight);
        
return flyweight;
      }

   }

   
   
protected abstract Flyweight createNewFlyweight(Object key);
}


        FlyweightPattern抽象方面包含一个享元池集合。这个集合会记住已经创建的重型对象,因此,在可用时,可以把享元设置成现有的重型对象。
        由于抽象方面不知道如何创建不同的具有享元对象,所以它定义了一个抽象方法createNewFlyweight(...)。
同时还包含flyweightCreation(Object)抽象切入点,它用于捕获何时创建被指定为享元的对象。这个切入点使用关联的around()通知,允许FlyweightPattern重写享元对象的创建,使用checkFlyweight(...)方法通过检查是否可以利用现有的重型对象来设计模式的规则,从而根据需要创建新的重型对象。
package com.aspectj;

public aspect PrintableCharacterFlyweight extends FlyweightPattern 
{
   declare parents : PrintableCharacter 
implements Flyweight;

   
protected pointcut flyweightCreation(Object key) : call(public com.oreilly.aspectjcookbook.PrintableCharacter.new(Character)) && args(key);
   
   
protected Flyweight createNewFlyweight(Object key)
   
{
      
return new PrintableCharacter((Character) key);
   }

}


三.实现适配器模式
        适配器模式提供一种方式,把从一个类发送的消息更改成为真正的目标类所期待的消息,使消息适合于两个粘连在一起。
package com.aspectj;

public aspect PrinterScreenAdapter 
{
  declare parents : Screen 
implements Printer;

  
public void Screen.print(String s)
  
{
    outputToScreen(s);
  }

}

四.实现桥接模式
        桥接模式把类与一种特定实现的底层特征分离开,使得可以应用不同的实现,而不会影响类的客户。
package com.aspectj;

public class Window
{
   
public void drawText(String text)
   
{
      
   }

   
   
public void drawRect()
   
{
      
   }

}

package com.aspectj;

public aspect XWindowBridge perthis(captureAllBridgedCalls())
{
      
private XWindow imp = new XWindow();
      
      
public pointcut captureDrawText(String text) : execution(public void Window.drawText(String)) && args(text);
      
      
public pointcut captureDrawRect() : execution(public void Window.drawRect());
      
      
public pointcut captureAllBridgedCalls() : captureDrawText(String) || captureDrawRect();
      
      
void around(String text) : captureDrawText(text)
      
{
         imp.drawText(text);
      }

      
      
void around() : captureDrawRect()
      
{
         imp.drawLine();
         imp.drawLine();
         imp.drawLine();
         imp.drawLine();
      }

}



        XWindowBridge方面捕获需要导向XWindow类上特定调用的Window类上的所有方法。例如,Window类上的drawRect()方法会在XWindow类上产生4个调用,但是通过使用桥接模式,Window类不必将这些调用硬编码进它的行为中。
        通过使用prethis(...)方面实例化策略,将会为通过captureAllBridgedCalls()切入点指定的每个新的桥接Window对象创建一个新方面。这意味着每个Window对象都有它自己的XWindow实现对象的副本。

五.实现装饰模式
        装饰模式扩展了类方法的行为,同时维持其现有的公共接口,而无需类知道或关心扩展。
package com.aspectj;

public abstract aspect DecoratorPattern 
{
   
public interface DecoratedComponent
   
{
   }
;
   
   
private boolean DecoratedComponent.decorated = false;
   
   
public void DecoratedComponent.setDecorated(boolean decorated)
   
{
      
this.decorated = decorated;
   }

   
   
public boolean DecoratedComponent.isDecorated()
   
{
      
return this.decorated;
   }

}


package com.aspectj;

public aspect TextDisplayDecorator extends DecoratorPattern 
{
  declare parents : TextDisplay 
implements DecoratedComponent;

  
public pointcut selectDecorators(Object object) : call(public void TextDisplay.display(String))
    
&& target(object);
  
  before(Object object) : selectDecorators(object) 
&& if(((DecoratedComponent)object).isDecorated())
  
{
     System.out.print(
"<Decoration>");
  }

  
  after(Object object) : selectDecorators(object) 
&& if(((DecoratedComponent)object).isDecorated())
  
{
     System.out.print(
"</Decoration>");
  }

}


package com.aspectj;

public class TextDisplay
{
    
public void display(String text)
    
{
        System.out.print(text);
    }

}

六.实现代理模式
        代理模式允许开发人员提供代理对象来代替实际的对象,以防需要委托或控制对真实对象的访问。
package com.aspectj;

import org.aspectj.lang.JoinPoint;

public abstract aspect ProxyPattern 
{

    
protected interface Subject
    
{
    }


    
protected abstract pointcut requestTriggered();

    
private pointcut accessByCaller(Object caller) : requestTriggered() && this(caller);
    
    
private pointcut accessByUnknown() : requestTriggered() && !accessByCaller(Object);

    Object around(Object caller, Subject subject) : accessByCaller(caller)
        
&& target(subject)
    
{
        
if (reject(caller, subject, thisJoinPoint))
        
{
            
return rejectRequest(caller, subject, thisJoinPoint);
        }

        
else if (delegate(caller, subject, thisJoinPoint))
        
{
            
return delegateRequest(caller, subject, thisJoinPoint);
        }


        
return proceed(caller, subject);
    }

    
    Object around(Subject subject) : accessByUnknown()
    
&& target(subject)
    
{
       
// Without a caller then reject does not really make sense
       
// as there is no way of deciding to reject or not
       if (delegate(null, subject, thisJoinPoint))
        
{
            
return delegateRequest(null, subject, thisJoinPoint);
        }


        
return proceed(subject);
    }


    
protected abstract boolean reject(
        Object caller,
        Subject subject,
        JoinPoint joinPoint);

    
protected abstract boolean delegate(
        Object caller,
        Subject subject,
        JoinPoint joinPoint);

    
protected abstract Object rejectRequest(
        Object caller,
        Subject subject,
        JoinPoint joinPoint);

    
protected abstract Object delegateRequest(
        Object caller,
        Subject subject,
        JoinPoint joinPoint);
}


        代理模式的抽象方面定义封装了Subject()的角色,它应用于需要定义代理逻辑的对象。对于可能应用代理的两种情况(委托和保护)中的任何一个情况,都存在一条定义的路径。通过它来检查和委托或者拒绝对主题的调用,这取决于继承子方面中包含的逻辑。
        代理模式的这个方面实现的最重要的优点是:目标应用程序的原始类不必知道将在代理情况下涉及它们。这是绝对关键的,因为这可以保护应用程序中的对象集合的安全,并其他代理敏感的考虑事项不会影响原始类的设计目标。
package com.aspectj;

import org.aspectj.lang.JoinPoint;

public aspect DelegationProxy extends ProxyPattern 
{
    declare parents : RealSubject 
implements Subject;

    
protected pointcut requestTriggered() : call(* RealSubject.write(..));

    
protected boolean reject(
        Object caller,
        Subject subject,
        JoinPoint joinPoint)
    
{

        
return false;

    }


    
protected boolean delegate(
        Object caller,
        Subject subject,
        JoinPoint joinPoint)
    
{
        
return true;
    }


    
protected Object rejectRequest(
        Object caller,
        Subject subject,
        JoinPoint joinPoint)
    
{
        
return null;
    }


    
protected Object delegateRequest(
        Object caller,
        Subject subject,
        JoinPoint joinPoint)
    
{
        Object[] args 
= joinPoint.getArgs();
        
if (args != null)
        
{
            AnotherRealSubject.write((String) args[
0]);
        }

        
else
        
{
            AnotherRealSubject.write(
"");
        }

        
return null;
    }

}




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


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


网站导航:
 

公告


导航

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

统计

常用链接

留言簿(4)

随笔分类

随笔档案

收藏夹

搜索

最新评论

阅读排行榜

评论排行榜