【IT168 技术文档】工厂方法模式根据产品的等级结构使用对应的工厂来创建特定的产品,它一般包括抽象工厂、具体工厂和抽象产品、具体产品,每一个特定工厂用于创建一个对应的产品。模式的简易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实现抽象工厂模式。