D 的个人博客

全职做开源,自由职业者

  menu

工厂方法(Factory Method)模式的Java实现[00原创]

这次的实例讲的是在一个果园中种有 3 种水果,勤劳的园丁负责照看它们,当有客户需要水果的时候就给他们。

1. 工厂方法实例类图




2. Java实现代码


package cn.edu.ynu.sei.factoryMethod;

/**
 * 果园园丁接口
 * 
 * 
@author 88250
 * 
@version 1.0.0, 2007-8-12
 * @uml.dependency supplier="cn.edu.ynu.sei.factoryMethod.Fruit"
 
*/
public interface FruitGardener
{
    
/**
     * 工厂方法
     * 
     * 
@return 水果作物
     
*/
    
public abstract Fruit factory();

    
/**
     * @uml.property name="client"
     * @uml.associationEnd inverse="fruitGardener:cn.edu.ynu.sei.factoryMethod.Client"
     
*/
    
public Client client = null;
}


package cn.edu.ynu.sei.factoryMethod;

/**
 * 苹果园园丁
 * 
 * 
@author 88250
 * 
@version 1.0.0, 2007-8-12
 
*/
public class AppleGardener implements FruitGardener
{

    
/**
     * 工厂方法,返回苹果作物的实例
     
*/
    @Override
    
public Fruit factory()
    {
    
return new Apple();
    }

}


package cn.edu.ynu.sei.factoryMethod;

/**
 * 草莓园园丁
 * 
 * 
@author 88250
 * 
@version 1.0.0, 2007-8-12
 
*/
public class StrawberryGardener implements FruitGardener
{

    
/**
     * 工厂方法,返回草莓作物实例
     
*/
    @Override
    
public Fruit factory()
    {
    
return new Strawberry();
    }

}


package cn.edu.ynu.sei.factoryMethod;

/**
 * 葡萄园园丁
 * 
 * 
@author 88250
 * 
@version 1.0.0, 2007-8-12
 
*/
public class GrapeGardener implements FruitGardener
{
    
/**
     * 工厂方法,返回葡萄作物对象
     
*/
    @Override
    
public Fruit factory()
    {
    
return new Grape();
    }

}


package cn.edu.ynu.sei.factoryMethod;

/**
 * 水果作物接口
 * 
@author 88250
 * 
@version 1.0.0, 2007-8-12
 
*/
public interface Fruit
{

    
/**
     * 作物生长
     
*/
    
public abstract void grow();

    
/**
     * 收获作物
     
*/
    
public abstract void harvest();

    
/**
     * 种植作物
     
*/
    
public abstract void plant();

}


package cn.edu.ynu.sei.factoryMethod;

/**
 * 苹果作物
 * 
 * 
@author 88250
 * 
@version 1.0.0, 2007-8-12
 
*/
public class Apple implements Fruit
{
    
/**
     * 树龄
     
*/
    
private int treeAge;

    
/*
     * (non-Javadoc)
     * 
     * @see cn.edu.ynu.sei.factoryMethod.Fruit#grow()
     
*/
    @Override
    
public void grow()
    {
    System.out.println(
"Apple is growing....");
    }

    
/*
     * (non-Javadoc)
     * 
     * @see cn.edu.ynu.sei.factoryMethod.Fruit#harvest()
     
*/
    @Override
    
public void harvest()
    {
    System.out.println(
"Apple has been harvested.");
    }

    
/*
     * (non-Javadoc)
     * 
     * @see cn.edu.ynu.sei.factoryMethod.Fruit#plant()
     
*/
    @Override
    
public void plant()
    {
    System.out.println(
"Apple has been planted.");
    }

    
/**
     * 返回树龄
     * 
     * 
@return 树龄
     
*/
    
public int getTreeAge()
    {
    
return treeAge;
    }

    
/**
     * 设置树龄
     * 
     * 
@param treeAge
     *                树龄
     
*/
    
public void setTreeAge(int treeAge)
    {
    
this.treeAge = treeAge;
    }
}


package cn.edu.ynu.sei.factoryMethod;

/**
 * 草莓作物
 * 
 * 
@author 88250
 * 
@version 1.0.0, 2007-8-13
 
*/
public class Strawberry implements Fruit
{

    @Override
    
public void grow()
    {
    System.out.println(
"Strawberry is growing....");
    }

    @Override
    
public void harvest()
    {
    System.out.println(
"Strawberry has been harvested.");
    }

    @Override
    
public void plant()
    {
    System.out.println(
"Strawberry has been planted.");
    }

}


package cn.edu.ynu.sei.factoryMethod;

/**
 * 葡萄作物
 * 
 * 
@author 88250
 * 
@version 1.0.0, 2007-8-12
 
*/
public class Grape implements Fruit
{
    
/**
     * 无籽葡萄?
     
*/
    
private boolean seedless;
    
    
/*
     * (non-Javadoc)
     * 
     * @see cn.edu.ynu.sei.factoryMethod.Fruit#grow()
     
*/
    @Override
    
public void grow()
    {
    System.out.println(
"Grape is growing....");
    }

    
/*
     * (non-Javadoc)
     * 
     * @see cn.edu.ynu.sei.factoryMethod.Fruit#harvest()
     
*/
    @Override
    
public void harvest()
    {
    System.out.println(
"Grape has been harvested.");
    }

    
/*
     * (non-Javadoc)
     * 
     * @see cn.edu.ynu.sei.factoryMethod.Fruit#plant()
     
*/
    @Override
    
public void plant()
    {
    System.out.println(
"Grape has been planted.");
    }
    
    
/**
     * 是否无籽?
     * 
@return 
     
*/
    
public boolean getSeedless()
    {
    
return seedless;
    }
    
    
/**
     * 设置是否无籽
     * 
@param seedless
     
*/
    
public void setSeedless(boolean seedless)
    {
    
this.seedless = seedless;
    }
}


package cn.edu.ynu.sei.factoryMethod;

/**
 * 果园的客户
 * 
 * 
@author 88250
 * 
@version 1.0.0, 2007-8-13
 
*/
public class Client
{
    
/**
     * 主程序入口点
     * 
     * 
@param args
     *                <code>null</code>
     
*/
    
public static void main(String[] args)
    {
    Fruit apple, strawberry, grape;

    fruitGardener 
= new AppleGardener();

    apple 
= fruitGardener.factory();
    apple.plant();
    
    fruitGardener 
= new StrawberryGardener();
    strawberry 
= fruitGardener.factory();
    strawberry.plant();
    strawberry.grow();
    
    fruitGardener 
= new GrapeGardener();
    grape 
= fruitGardener.factory();
    grape.harvest();
    
    apple.harvest();
    }

    
/**
     * @uml.property name="fruitGardener"
     * @uml.associationEnd inverse="client1:cn.edu.ynu.sei.factoryMethod.FruitGardener"
     
*/
    
private static FruitGardener fruitGardener;

    
/**
     * Getter of the property <tt>fruitGardener</tt>
     * 
     * 
@return Returns the fruitGardener.
     * @uml.property name="fruitGardener"
     * @uml.associationEnd inverse="client1:cn.edu.ynu.sei.factoryMethod.FruitGardener"
     
*/
    
public FruitGardener getFruitGardener()
    {
    
return fruitGardener;
    }

    
/**
     * Setter of the property <tt>fruitGardener</tt>
     * 
     * 
@param fruitGardener
     *                The fruitGardener to set.
     * @uml.property name="fruitGardener"
     * @uml.associationEnd inverse="client1:cn.edu.ynu.sei.factoryMethod.FruitGardener"
     
*/
    
public void setFruitGardener(FruitGardener fruitGardener)
    {
    Client.fruitGardener 
= fruitGardener;
    }

}
 

3. 总结

工厂方法模式是简单工厂模式的一个“升级”,其核心由简单工厂中的具体类变成了现在的抽象接口。这样做的好处是可以完全支持OCP,既“开-闭”原则。当系统需要加入一个新的产品时,那么所要做的就是加入这个新产品的类以及对应的工厂类。客户端完全不用修改,也没有必要修改抽象工厂角色或者其他已有的具体工厂角色,所以说这个模式是完全支持OCP的。

抽象工厂角色和抽象产品角色都可以选择由Java接口或者是Java抽象类来实现。如果具体工厂角色具有共同逻辑的话,那么这些共同逻辑就可以向上移动到抽象工厂角色中,这也就意味着抽象工厂角色应该使用Java抽象类来实现,在抽象角色里提供默认的工厂方法,相反的华就应该用Java接口实现,对抽象产品也是一样的。

这里需要注意的是任何方法都不应该复写它的基类中的已经实现的方法,否则将违反DIP
(Dependency-Inversion Principles) 依赖倒置原则,细节请参考 面向对象的设计原则摘要

4. 参考文献

  《Design Patterns》、《Java与模式》