《AspectJ Cookbook》讀書筆記十八: 實(shí)現(xiàn)結(jié)構(gòu)型面向?qū)ο笤O(shè)計(jì)模式
一.實(shí)現(xiàn)復(fù)合模式
復(fù)合模式能夠把集合中的對象組合在一起,并且以某種方式與整個(gè)組交互,這種交互式類似于同組中的單個(gè)成員進(jìn)行交互。
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);
}
}
二.實(shí)現(xiàn)享元模式
享元模式提供了一些機(jī)制,利用這些機(jī)制通過在合適的地方共享對象,可以把細(xì)粒度的對象納入到OO設(shè)計(jì)中,而不會(huì)帶來資源和性能損失。重型對象潛在地通過許多享元對象來封裝要引用的實(shí)際數(shù)據(jù)。
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抽象方面包含一個(gè)享元池集合。這個(gè)集合會(huì)記住已經(jīng)創(chuàng)建的重型對象,因此,在可用時(shí),可以把享元設(shè)置成現(xiàn)有的重型對象。
由于抽象方面不知道如何創(chuàng)建不同的具有享元對象,所以它定義了一個(gè)抽象方法createNewFlyweight(...)。
同時(shí)還包含flyweightCreation(Object)抽象切入點(diǎn),它用于捕獲何時(shí)創(chuàng)建被指定為享元的對象。這個(gè)切入點(diǎn)使用關(guān)聯(lián)的around()通知,允許FlyweightPattern重寫享元對象的創(chuàng)建,使用checkFlyweight(...)方法通過檢查是否可以利用現(xiàn)有的重型對象來設(shè)計(jì)模式的規(guī)則,從而根據(jù)需要?jiǎng)?chuàng)建新的重型對象。
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);
}
}
三.實(shí)現(xiàn)適配器模式
適配器模式提供一種方式,把從一個(gè)類發(fā)送的消息更改成為真正的目標(biāo)類所期待的消息,使消息適合于兩個(gè)粘連在一起。
package com.aspectj;

public aspect PrinterScreenAdapter
{
declare parents : Screen implements Printer;

public void Screen.print(String s)
{
outputToScreen(s);
}
}
四.實(shí)現(xiàn)橋接模式
橋接模式把類與一種特定實(shí)現(xiàn)的底層特征分離開,使得可以應(yīng)用不同的實(shí)現(xiàn),而不會(huì)影響類的客戶。
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方面捕獲需要導(dǎo)向XWindow類上特定調(diào)用的Window類上的所有方法。例如,Window類上的drawRect()方法會(huì)在XWindow類上產(chǎn)生4個(gè)調(diào)用,但是通過使用橋接模式,Window類不必將這些調(diào)用硬編碼進(jìn)它的行為中。
通過使用prethis(...)方面實(shí)例化策略,將會(huì)為通過captureAllBridgedCalls()切入點(diǎn)指定的每個(gè)新的橋接Window對象創(chuàng)建一個(gè)新方面。這意味著每個(gè)Window對象都有它自己的XWindow實(shí)現(xiàn)對象的副本。
五.實(shí)現(xiàn)裝飾模式
裝飾模式擴(kuò)展了類方法的行為,同時(shí)維持其現(xiàn)有的公共接口,而無需類知道或關(guān)心擴(kuò)展。
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);
}
}
六.實(shí)現(xiàn)代理模式
代理模式允許開發(fā)人員提供代理對象來代替實(shí)際的對象,以防需要委托或控制對真實(shí)對象的訪問。
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()的角色,它應(yīng)用于需要定義代理邏輯的對象。對于可能應(yīng)用代理的兩種情況(委托和保護(hù))中的任何一個(gè)情況,都存在一條定義的路徑。通過它來檢查和委托或者拒絕對主題的調(diào)用,這取決于繼承子方面中包含的邏輯。
代理模式的這個(gè)方面實(shí)現(xiàn)的最重要的優(yōu)點(diǎn)是:目標(biāo)應(yīng)用程序的原始類不必知道將在代理情況下涉及它們。這是絕對關(guān)鍵的,因?yàn)檫@可以保護(hù)應(yīng)用程序中的對象集合的安全,并其他代理敏感的考慮事項(xiàng)不會(huì)影響原始類的設(shè)計(jì)目標(biāo)。
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;
}
}

復(fù)合模式能夠把集合中的對象組合在一起,并且以某種方式與整個(gè)組交互,這種交互式類似于同組中的單個(gè)成員進(jìn)行交互。
























































































二.實(shí)現(xiàn)享元模式
享元模式提供了一些機(jī)制,利用這些機(jī)制通過在合適的地方共享對象,可以把細(xì)粒度的對象納入到OO設(shè)計(jì)中,而不會(huì)帶來資源和性能損失。重型對象潛在地通過許多享元對象來封裝要引用的實(shí)際數(shù)據(jù)。












































FlyweightPattern抽象方面包含一個(gè)享元池集合。這個(gè)集合會(huì)記住已經(jīng)創(chuàng)建的重型對象,因此,在可用時(shí),可以把享元設(shè)置成現(xiàn)有的重型對象。
由于抽象方面不知道如何創(chuàng)建不同的具有享元對象,所以它定義了一個(gè)抽象方法createNewFlyweight(...)。
同時(shí)還包含flyweightCreation(Object)抽象切入點(diǎn),它用于捕獲何時(shí)創(chuàng)建被指定為享元的對象。這個(gè)切入點(diǎn)使用關(guān)聯(lián)的around()通知,允許FlyweightPattern重寫享元對象的創(chuàng)建,使用checkFlyweight(...)方法通過檢查是否可以利用現(xiàn)有的重型對象來設(shè)計(jì)模式的規(guī)則,從而根據(jù)需要?jiǎng)?chuàng)建新的重型對象。














三.實(shí)現(xiàn)適配器模式
適配器模式提供一種方式,把從一個(gè)類發(fā)送的消息更改成為真正的目標(biāo)類所期待的消息,使消息適合于兩個(gè)粘連在一起。











四.實(shí)現(xiàn)橋接模式
橋接模式把類與一種特定實(shí)現(xiàn)的底層特征分離開,使得可以應(yīng)用不同的實(shí)現(xiàn),而不會(huì)影響類的客戶。









































XWindowBridge方面捕獲需要導(dǎo)向XWindow類上特定調(diào)用的Window類上的所有方法。例如,Window類上的drawRect()方法會(huì)在XWindow類上產(chǎn)生4個(gè)調(diào)用,但是通過使用橋接模式,Window類不必將這些調(diào)用硬編碼進(jìn)它的行為中。
通過使用prethis(...)方面實(shí)例化策略,將會(huì)為通過captureAllBridgedCalls()切入點(diǎn)指定的每個(gè)新的橋接Window對象創(chuàng)建一個(gè)新方面。這意味著每個(gè)Window對象都有它自己的XWindow實(shí)現(xiàn)對象的副本。
五.實(shí)現(xiàn)裝飾模式
裝飾模式擴(kuò)展了類方法的行為,同時(shí)維持其現(xiàn)有的公共接口,而無需類知道或關(guān)心擴(kuò)展。


















































六.實(shí)現(xiàn)代理模式
代理模式允許開發(fā)人員提供代理對象來代替實(shí)際的對象,以防需要委托或控制對真實(shí)對象的訪問。


































































代理模式的抽象方面定義封裝了Subject()的角色,它應(yīng)用于需要定義代理邏輯的對象。對于可能應(yīng)用代理的兩種情況(委托和保護(hù))中的任何一個(gè)情況,都存在一條定義的路徑。通過它來檢查和委托或者拒絕對主題的調(diào)用,這取決于繼承子方面中包含的邏輯。
代理模式的這個(gè)方面實(shí)現(xiàn)的最重要的優(yōu)點(diǎn)是:目標(biāo)應(yīng)用程序的原始類不必知道將在代理情況下涉及它們。這是絕對關(guān)鍵的,因?yàn)檫@可以保護(hù)應(yīng)用程序中的對象集合的安全,并其他代理敏感的考慮事項(xiàng)不會(huì)影響原始類的設(shè)計(jì)目標(biāo)。























































posted on 2008-08-28 10:49 Brian 閱讀(1051) 評論(0) 編輯 收藏 所屬分類: 《AspectJ Cookbook》讀書筆記