本文将继续介绍使用AspectJ实现设计模式之工厂方法模式,文章以农场园丁管理水果(读过Java与模式的读者会很熟悉它)例子的形式描述了工厂方法模式AspectJ版本的参考实现。
工厂方法模式根据产品的等级结构使用对应的工厂来创建特定的产品,它一般包括抽象工厂、具体工厂和抽象产品、具体产品,每一个特定工厂用于创建一个对应的产品。模式的简易UML图例如下
下面是使用AspectJ实现的工厂方法模式UML图
抽象方面FactoryMethodProtocol很简单只定义了抽象pointcut createMethod用于捕捉特定应用的创建方法(也可以省略)。
FactoryMethodProtocol抽象方面
public abstract aspect FactoryMethodProtocol {
abstract pointcut createMethod();}
FactoryMethodImpl.java
public aspect FactoryMethodImpl extends FactroyMethodProtocol{
public Fruit FruitGardener.factory(){//为创建接口定义工厂方法
return null;
}
//Inter-type声明具体创建类并实现创建接口
declare parents : AppleGardener implements FruitGardener;
declare parents : GrapeGardener implements FruitGardener;
//指定createMethod捕捉FruitGardener及其子类的创建方法
pointcut createMethod() : call(Fruit FruitGardener+.factory());
Fruit around(FruitGardener gardener) : target(gardener) && createMethod(){
return chooseGardener(gardener);//工厂方法返回抽象产品。
}
private Fruit chooseGardener(FruitGardener gardener){
if(gardener instanceof AppleGardener){
return new Apple();
}
else if(gardener instanceof GrapeGardener){
return new Grape();
}
else{
throw new RuntimeException("No such kind of fruit");
}
}
//声明编译时错误:当客户直接使用new创建具体产品时发生。
//目的:强制程序完全按照工厂方法的形式创建产品。
//可选为声明警告 declare warning : [pointcut] : [warn msg]
declare error : !(within(FruitGardener+) && !createMethod())
&&!within(FactoryMethodImpl) && call(Fruit+.new(..))
: "You can only create fruits through the method factory provided by FruitGardener and its subclass";
}
三个空的创建对象声明,其创建逻辑在FactoryMethodImpl方面中定义
public interface FruitGardener {}
public class GrapeGardener {}
public class AppleGardener {}
Fruit.java抽象产品类
public abstract class Fruit {
public abstract void grow();
public abstract void harvest();
public abstract void plant();
}
Apple.java产品类
public class Apple extends Fruit{
public void grow(){
System.out.println("Apple is growing...");
}
public void harvest(){
System.out.println("Apple has been harvested");
}
public void plant(){
System.out.println("Apple has been planted");
}
}
Grape.java产品类
public class Grape extends Fruit{
public void grow(){
System.out.println("Grape is growing...");
}
public void harvest(){
System.out.println("Grape has been harvested");
}
public void plant(){
System.out.println("Grape has been planted");
}
}
Demo.java测试代码
public class Demo {
public static void main(String[] args) {
FruitGardener gardener=new AppleGardener();
Fruit fruit=gardener.factory();//创建Apple
fruit.grow();
fruit.harvest();
fruit.plant();
gardener=new GrapeGardener();
fruit=gardener.factory();//创建Grape
fruit.grow();
fruit.harvest();
fruit.plant();
//new Apple();new Grape();//产生编译错误,不能直接生成产品
}
}
测试代码使用苹果和葡萄园丁分别创建了苹果和葡萄,其运行结果如下
Apple is growing...
Apple has been harvested.
Apple has been planted.
Grape is growing..
Grape has been harvested.
grape has been planted.
有一点值得注意,如果在Demo中加入new Apple()或new Grape()等直接创建产品的语句,则ajc编译器会根据在FactoryMethodImpl方面中声明的错误而无法编译成功,并会得到如下输出:
D:\JavaDev\jbuider\AOPFactoryMethod\src\aopfactorymethod\Demo.java 26 You can only create fruits through the method factory provided by FruitGardener and its subclass 1 error.
至此,我已经使用AspectJ完全实现了一个使用工厂方法模式设计的农场园丁的例子。本系列之四将介绍如何用AspectJ实现抽象工厂模式。
参考资料
1.<<Java与模式>> 阎宏著 电子工业出版社
2.http://www.eclipse.org/aspectj/
声明
本文由starchu1981保留版权,如果需要转贴请写明作者和出处。