*工厂模式专门负责将大量有共同接口的类实例化。工厂模式的几种形态:
简单工厂模式、工厂方法模式、抽象工厂模式*
简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例
1.原理及总结
简单工厂模式的结构
角色与结构
简单工厂模式就是由一个工厂类根据传入的参量决定出创建哪一种产品类实例。如下图:
从上图可以看出,简单工厂模式涉及到工厂角色、抽象产品角色以及具体产品角色等三个角色:
工厂类(Creator)角色:担任这个角色的是工厂方法模式的核心,含有与应用紧密相关的商业逻辑。工厂类在客户端的直接调用下创建产品对象,它往往由一个具体java类实现。
抽象产品(Product)角色:担任这个角色的类是由工厂方法模式所创建的对象的父类,或它们共同拥有的接口。抽象产品角色可以用一个java接口或java抽象类实现。
- 具体产品(Concrete Product)角色:工厂方法模式所创建的任何对象都是这个角色的实例,具体产品角色由一个具体java类实现。
源代码
Creator类的源代码
public class Creator
{
/**
*静态工厂方法
*/
public static Product factory()
{
return new ConcreteProduct();
}
}
抽象角色Product接口的源代码
public interface Product
{
}
具体产品角色ConcreteProduct类的源代码
public class ConcreteProduct implements Product
{
public ConcreteProduct(){}
}
虽然在这个简单的示意性实现里面只给出了一个具体产品类,但是实际应用中一般都会遇到多个具体产品类的情况。
2.具体实例
实例
有一个农场公司,专门向市场销售水果。在这个系统需要描述的水果:
- 葡萄 Grape
- 草莓 Strawberry
- 苹果 Apple
构建结构图如下:
水果结构规定出所有的水果必须实现的接口,包括任何水果类必须具备的方法:种植 plain(),生长 grow()以及收获 harvest()。
源代码
接口Fruit的源代码
public interface Fruit {
/**
* 生长
*/
void grow();
/**
* 收获
*/
void harvest();
/**
* 种植
*/
void plant();
}
Apple类的源代码
public class Apple implements Fruit {
private int treeAge;
@Override
public void grow() {
// TODO Auto-generated method stub
log("Apple is growing...");
}
@Override
public void harvest() {
// TODO Auto-generated method stub
log("Apple has been harvested");
}
@Override
public void plant() {
// TODO Auto-generated method stub
log("Apple has been planted");
}
public static void log(String msg){
System.out.println(msg);
}
}
Grape类的源代码
public class Grape implements Fruit {
private boolean seedless;
@Override
public void grow() {
// TODO Auto-generated method stub
log("Grape is growing... ");
}
@Override
public void harvest() {
// TODO Auto-generated method stub
log("Grape has been harvested");
}
@Override
public void plant() {
// TODO Auto-generated method stub
log("Grape has been planted");
}
public static void log(String msg){
System.out.println(msg);
}
public boolean isSeedless() {
return seedless;
}
public void setSeedless(boolean seedless) {
this.seedless = seedless;
}
}
Strawberry类的源代码
public class Strawberry implements Fruit {
@Override
public void grow() {
// TODO Auto-generated method stub
log("Strawberry is growing");
}
@Override
public void harvest() {
// TODO Auto-generated method stub
log("Strawberry has been harvested");
}
@Override
public void plant() {
// TODO Auto-generated method stub
log("Strawberry has been planted");
}
public static void log(String msg){
System.out.println(msg);
}
}
工厂类FruitGardener类,其结构图如下所示:
FruitGardener类会根据客户端的要求,创建出不同的水果对象,比如苹果(Apple)葡萄(Grape)或草莓(Strawbeery)的实例。而如果接到不合法的要求,FruitGardener类会抛出BadFruitException异常,如下所示。
FruitGardener类的源代码
public class FruitGardener {
public static Fruit factory(String which)
throws BadFruitException
{
if(which.equalsIgnoreCase("apple"))
{
return new Apple();
}else if(which.equalsIgnoreCase("strawberry"))
{
return new Strawberry();
}
else if(which.equalsIgnoreCase("grape"))
{
return new Grape();
}
else
{
throw new BadFruitException("Bad fruit request");
}
}
}
BadFruitException类的源代码:
public class BadFruitException extends Exception {
public BadFruitException(String msg)
{
super(msg);
}
}
客户端的源代码:
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
FruitGardener gardener=new FruitGardener();
try {
Fruit f1=gardener.factory("apple");
f1.grow();
gardener.factory("strawberry");
gardener.factory("Grape");
} catch (BadFruitException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
3.优缺点
简单工厂模式的优缺点:
优点:这个类含有必要的判断逻辑,可以决定在什么时候创建哪一个类的实例。而客户端则可以免除直接创建产品对象的责任,而仅仅负责“消费”产品。简单工厂模式通过这种做法实现了对责任的分割。
缺点:当产品类有复杂的多层次等级结构时,工厂类只有它自己。以不变应万变,就是模式的缺点。
这个工厂类集中了所有产品的创建逻辑,一旦出现问题,所有的类都受到影响。
将这么多的逻辑集中放在一个类里面的另一个缺点是,当产品类有不同的接口种类时,工厂类需要判断在什么时候创建某种产品。这种对时机的判断和哪一种具体产品的判断逻辑混合在一起,使得系统在将来功能扩展时比较困难。这个缺点在工厂方法模式中得到克服。
- 由于简单工厂方法使用静态方法作为工厂方法,而静态方法无法由子类继承,因此,工厂角色无法形成基于继承的等级结构。这个缺点会在工厂方法模式中克服。
- 不符合开闭原则