本次实例继续上次 工厂方法 中的果园农场。这次,该农场公司引进塑料大棚技术,在大棚里种植热带(Tropical)水果和蔬菜。
1. 抽象工厂实例类图
2. Java实现代码
package cn.edu.ynu.sei.abstractFactory;
/**
* 水果接口
* @author 88250
* @version 1.0.0, 2007-8-13
* @see cn.edu.ynu.sei.factoryMethod.Fruit
*/
public interface Fruit
{
}
/**
* 水果接口
* @author 88250
* @version 1.0.0, 2007-8-13
* @see cn.edu.ynu.sei.factoryMethod.Fruit
*/
public interface Fruit
{
}
package cn.edu.ynu.sei.abstractFactory;
/**
* 热带水果
*
* @author 88250
* @version 1.0.0, 2007-8-13
*/
public class TropicalFruit implements Fruit
{
/**
* 水果名
*/
private String name;
/**
* 构造器
* @param name 果名
*/
public TropicalFruit(String name)
{
this.name = name;
}
/**
* @return the name
*/
public String getName()
{
return name;
}
/**
* @param name the name to set
*/
public void setName(String name)
{
this.name = name;
}
}
/**
* 热带水果
*
* @author 88250
* @version 1.0.0, 2007-8-13
*/
public class TropicalFruit implements Fruit
{
/**
* 水果名
*/
private String name;
/**
* 构造器
* @param name 果名
*/
public TropicalFruit(String name)
{
this.name = name;
}
/**
* @return the name
*/
public String getName()
{
return name;
}
/**
* @param name the name to set
*/
public void setName(String name)
{
this.name = name;
}
}
package cn.edu.ynu.sei.abstractFactory;
/**
* 北方水果接口
*
* @author 88250
* @version 1.0.0, 2007-8-13
*/
public class NorthernFruit implements Fruit
{
/**
* 水果名
*/
private String name;
/**
* 构造器
* @param name 果名
*/
public NorthernFruit(String name)
{
this.name = name;
}
/**
* @return the name
*/
public String getName()
{
return name;
}
/**
* @param name the name to set
*/
public void setName(String name)
{
this.name = name;
}
}
/**
* 北方水果接口
*
* @author 88250
* @version 1.0.0, 2007-8-13
*/
public class NorthernFruit implements Fruit
{
/**
* 水果名
*/
private String name;
/**
* 构造器
* @param name 果名
*/
public NorthernFruit(String name)
{
this.name = name;
}
/**
* @return the name
*/
public String getName()
{
return name;
}
/**
* @param name the name to set
*/
public void setName(String name)
{
this.name = name;
}
}
package cn.edu.ynu.sei.abstractFactory;
/**
* 蔬菜接口
*
* @author 88250
* @version 1.0.0, 2007-8-13
* @see cn.edu.ynu.sei.factoryMethod.Fruit
*/
public interface Veggie
{
}
/**
* 蔬菜接口
*
* @author 88250
* @version 1.0.0, 2007-8-13
* @see cn.edu.ynu.sei.factoryMethod.Fruit
*/
public interface Veggie
{
}
package cn.edu.ynu.sei.abstractFactory;
/**
* 北方蔬菜
*
* @author 88250
* @version 1.0.0, 2007-8-13
*/
public class NorthernVeggie implements Veggie
{
/**
* 蔬菜名
*/
private String name;
/**
* 构造器
* @param name 蔬菜名
*/
public NorthernVeggie(String name)
{
this.name = name;
}
/**
* @return the name
*/
public String getName()
{
return name;
}
/**
* @param name the name to set
*/
public void setName(String name)
{
this.name = name;
}
}
/**
* 北方蔬菜
*
* @author 88250
* @version 1.0.0, 2007-8-13
*/
public class NorthernVeggie implements Veggie
{
/**
* 蔬菜名
*/
private String name;
/**
* 构造器
* @param name 蔬菜名
*/
public NorthernVeggie(String name)
{
this.name = name;
}
/**
* @return the name
*/
public String getName()
{
return name;
}
/**
* @param name the name to set
*/
public void setName(String name)
{
this.name = name;
}
}
package cn.edu.ynu.sei.abstractFactory;
/**
* 热带蔬菜
*
* @author 88250
* @version 1.0.0, 2007-8-13
*/
public class TropicalVeggie implements Veggie
{
/**
* 蔬菜名
*/
private String name;
/**
* 构造器
* @param name 蔬菜名
*/
public TropicalVeggie(String name)
{
this.name = name;
}
/**
* @return the name
*/
public String getName()
{
return name;
}
/**
* @param name the name to set
*/
public void setName(String name)
{
this.name = name;
}
}
/**
* 热带蔬菜
*
* @author 88250
* @version 1.0.0, 2007-8-13
*/
public class TropicalVeggie implements Veggie
{
/**
* 蔬菜名
*/
private String name;
/**
* 构造器
* @param name 蔬菜名
*/
public TropicalVeggie(String name)
{
this.name = name;
}
/**
* @return the name
*/
public String getName()
{
return name;
}
/**
* @param name the name to set
*/
public void setName(String name)
{
this.name = name;
}
}
package cn.edu.ynu.sei.abstractFactory;
/**
* 园丁接口
*
* @author 88250
* @version 1.0.0, 2007-8-13
*/
public interface Gardener
{
/**
* 水果工厂方法,产出一种水果
* @param name 水果名
* @return 水果
*/
public abstract Fruit createdFruit(String name);
/**
* 蔬菜的工厂方法产出一种蔬菜
* @param name 蔬菜名
* @return 蔬菜
*/
public abstract Veggie createVeggie(String name);
}
/**
* 园丁接口
*
* @author 88250
* @version 1.0.0, 2007-8-13
*/
public interface Gardener
{
/**
* 水果工厂方法,产出一种水果
* @param name 水果名
* @return 水果
*/
public abstract Fruit createdFruit(String name);
/**
* 蔬菜的工厂方法产出一种蔬菜
* @param name 蔬菜名
* @return 蔬菜
*/
public abstract Veggie createVeggie(String name);
}
package cn.edu.ynu.sei.abstractFactory;
/**
* 北方园园丁
*
* @author 88250
* @version 1.0.0, 2007-8-13
*/
public class NorthenGardener implements Gardener
{
@Override
public Fruit createdFruit(String name)
{
return new NorthernFruit(name);
}
@Override
public Veggie createVeggie(String name)
{
return new NorthernVeggie(name);
}
}
/**
* 北方园园丁
*
* @author 88250
* @version 1.0.0, 2007-8-13
*/
public class NorthenGardener implements Gardener
{
@Override
public Fruit createdFruit(String name)
{
return new NorthernFruit(name);
}
@Override
public Veggie createVeggie(String name)
{
return new NorthernVeggie(name);
}
}
package cn.edu.ynu.sei.abstractFactory;
/**
* 热带园园丁
*
* @author 88250
* @version 1.0.0, 2007-8-13
*/public class TropicalGardener implements Gardener
{
@Override
public Fruit createdFruit(String name)
{
return new TropicalFruit(name);
}
@Override
public Veggie createVeggie(String name)
{
return new TropicalVeggie(name);
}
}
/**
* 热带园园丁
*
* @author 88250
* @version 1.0.0, 2007-8-13
*/public class TropicalGardener implements Gardener
{
@Override
public Fruit createdFruit(String name)
{
return new TropicalFruit(name);
}
@Override
public Veggie createVeggie(String name)
{
return new TropicalVeggie(name);
}
}
3. 总结
这里我们还是讨论一下抽象工厂模式对面向对象原则中最基本的OCP原则的支持。
当增加一个新的产品族的时候我们只需要向系统中加入新的具体工厂角色和对应的具体产品角色,不需要修改原有的工厂或产品角色的代码,所以此时抽象模式是完全支持OCP的。
当增加新的产品等级结构时就需要修改相关的具体工厂代码。例如在农场公司系统中有一种热带水果类别继承于现用热带水果类别,这时我们不得不修改热带水果具体工厂的代码,新增加一个工厂方法给它。这样是不符合OCP的。所以抽象工厂只是在一定程度上支持OCP的,在设计的时候这点很值得我们注意。