学习《java与模式》 之 工厂模式

一  工厂模式

  (1)简单工厂

简单工厂模式又称静态工厂方法模式,就是有一个工厂类根据传入的参量决定创建出哪一类的产品类的实例。 先来看看它的组成:

1)    工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑。在java中它往往由一个具体类实现。

2)    抽象产品角色:它一般是具体产品继承的父类或者实现的接口。在java中由接口或者抽象类来实现。

3)     具体产品角色:工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现。

来用类图来清晰的表示下的它们之间的关系

 

        我们先来看一个例子:

package com.bin.factory;

/**
 * 水果接口
 */
public interface Fruit {

	void grow();
	
	void harvset();
	
	void plant();
}

实现类:

package com.bin.factory;

public class Apple implements Fruit {

	private int treeAge;

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

	@Override
	public void harvset() {
		System.out.print("Apple has bean harvsed");
	}

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

	public int getTreeAge() {
		return treeAge;
	}

	public void setTreeAge(int treeAge) {
		this.treeAge = treeAge;
	}
}
package com.bin.factory;

public class Grape implements Fruit {

	private boolean seedless;
	public boolean isSeedless() {
		return seedless;
	}

	public void setSeedless(boolean seedless) {
		this.seedless = seedless;
	}

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

	@Override
	public void harvset() {
		System.out.print("Grape has bean harvsed");
	}

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


}

package com.bin.factory;

public class Strawberry implements Fruit{

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

	@Override
	public void harvset() {
		System.out.print("Strawberry has bean harvsed");
	}

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


}

工厂类:

package com.bin.factory;

public class FruitGardener {

	public static Fruit factory(String which) throws BadFruitException
	{
		if(which.equalsIgnoreCase("apple")){
			return new Apple();
		}
		if(which.equalsIgnoreCase("strawberry")){
			return new Strawberry();
		}
		if(which.equalsIgnoreCase("grape")){
			return new Grape();
		}
		else {
			throw new BadFruitException("bad fruit request");
		}
	 
	}

}

异常类:

package com.bin.factory;

public class BadFruitException extends Exception {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public BadFruitException(String msg){
		super(msg);
	}
}


测试类:

package com.bin.factory;

public class Test1 {

	/**
	 * @param args
	 * @throws BadFruitException 
	 */
	public static void main(String[] args) throws BadFruitException {
		FruitGardener.factory("apple").grow();

	}

}


        多个抽象产品类和具体产品类的时候,简单工厂模式一般使用同一个工厂类,这样产品类的结构不会反映到工厂类中来,从而产品类的等级结构变化也不会 影响到工厂类。

        每个工程类可以有多个工厂类,譬如JAVA.TEXT.DATEFORMAT

        有时候可以省略掉抽象产品类角色例:

public classCreator {
   public static ConcreteProduct factory(){
     return new ConcreteProduct();
   }
}

public class ConcreteProduct{
      public ConcreteProduct();
}

      当然有时候三个独立的角色可以合并成一类,代码如下:

public class ConcreteProduct{
	public ConcreteProduct(){}
	/**
	 * 静态工厂方法
	 * @return
	 */
	public static ConcreteProduct factory(){
		return new ConcreteProduct();
	}
}
这个类跟单例有些相似,但是并不等于单例。单例模式构造子是私有的,客户的不能实例化,以后我们在阐述

下面是java中的dataFormat中使用简单工厂方法的一个用例

import java.util.Date;
import java.text.DateFormat;

/**
 * 格式化时间类 DateFormat.FULL = 0 DateFormat.DEFAULT = 2 DateFormat.LONG = 1
 * DateFormat.MEDIUM = 2 DateFormat.SHORT = 3
 */

public class Test {
    public static void main(String[] args) {
        Date d = new Date();
        String s;

        /** Date类的格式: Sat Apr 16 13:17:29 CST 2006 */
        System.out.println(d);

        System.out.println("******************************************");

        /** getDateInstance() */
        /** 输出格式: 2006-4-16 */
        s = DateFormat.getDateInstance().format(d);
        System.out.println(s);

        /** 输出格式: 2006-4-16 */
        s = DateFormat.getDateInstance(DateFormat.DEFAULT).format(d);
        System.out.println(s);

        /** 输出格式: 2006年4月16日 星期六 */
        s = DateFormat.getDateInstance(DateFormat.FULL).format(d);
        System.out.println(s);

        /** 输出格式: 2006-4-16 */
        s = DateFormat.getDateInstance(DateFormat.MEDIUM).format(d);
        System.out.println(s);

        /** 输出格式: 06-4-16 */
        s = DateFormat.getDateInstance(DateFormat.SHORT).format(d);
        System.out.println(s);

        /** 输出格式: 2006-01-01 00:00:00 */
        java.text.DateFormat format1 = new java.text.SimpleDateFormat(
                "yyyy-MM-dd hh:mm:ss");
        s = format1.format(new Date());
        System.out.println(s);

        /** 输出格式: 2006-01-01 01:00:00 */
        System.out.println((new java.text.SimpleDateFormat(
                "yyyy-MM-dd hh:mm:ss")).format(new Date()));

        /** 输出格式: 2006-01-01 13:00:00 */
        System.out.println((new java.text.SimpleDateFormat(
                "yyyy-MM-dd HH:mm:ss")).format(new Date()));

        /** 输出格式: 20060101000000 ***/
        java.text.DateFormat format2 = new java.text.SimpleDateFormat(
                "yyyyMMddhhmmss");
        s = format2.format(new Date());
        System.out.println(s);
    }
}    

(2 )工厂模式

       简单工厂模式必须知道一个产品,然后决定产品类应当被实例化,优点是客户端相对独立于产品创建过程,并且新产品引入的时候无需修改客户端,但是如有有新的产品加入到系统只弄个,就必须修改工厂类。

        工厂模式中,核心工厂类不再负责创建产品,具体的工作交与子类去做,这个类就变成抽象工厂角色,仅负责给出具体工厂子类必须实现的借口,而不必接触产品类应当被实例化这种细节。

       其各个角色关系可表述如下:

       抽象工厂(Creator)角色:是工厂方法模式的核心,与应用程序无关。任何在模式中创建的对象的工厂类必须实现这个接口。
       具体工厂(Concrete Creator)角色:这是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建产品对象。
      抽象产品(Product)角色:工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。
      具体产品(Concrete Product)角色:这个角色实现了抽象产品角色所定义的接口。某具体产品有专门的具体工厂创建,它们之间往往一一对应。
     我们用代码实现下:

    

package com.bin.factory.gongchang;
public interface Creator {
/**
 * 抽象工厂
 * @return
 */
	public Product factory();
}

package com.bin.factory.gongchang;
/**
 * 抽象产品
 * @author LMWL
 *
 */
public interface Product {

}
package com.bin.factory.gongchang;
/**
 * 具体工厂角色
 * @author LMWL
 *
 */
public class ConcreteCreator1 implements Creator {

	@Override
	public Product factory() {
		// TODO Auto-generated method stub
		return new ConcreteProduct1();
	}

}

package com.bin.factory.gongchang;
/**
 * 具体工厂角色
 * @author LMWL
 *
 */
public class ConcreteCreator2 implements Creator {

	@Override
	public Product factory() {
		// TODO Auto-generated method stub
		return new ConcreteProduct2();
	}

}

package com.bin.factory.gongchang;
/**
 * 具体产品角色
 * @author LMWL
 *
 */
public class ConcreteProduct1 implements Product {

	public ConcreteProduct1(){
		
	}
}

package com.bin.factory.gongchang;
/**
 * 具体产品角色
 * @author LMWL
 *
 */
public class ConcreteProduct2 implements Product {

	public ConcreteProduct2(){
		
	}
}

package com.bin.factory.gongchang;
/**
 * 客户端角色
 * @author LMWL
 *
 */
public class Client {
	private static Creator creator1,creator2;
	private static Product prod1,prod2;
	public static void main(String[] args){
		creator1 = new  ConcreteCreator1();
		 prod1 =creator1.factory();
		creator2 = new  ConcreteCreator2();
		 prod2=creator2.factory();
	}
}


我们也可以把简单工厂中所举得一个水果例子改成工厂模式俩解决:

package com.bin.factory.fruit;
/**
 * 抽象工厂,所有工厂继承此类
 */
public interface FruitGardener {

	public Fruit factory();
}

package com.bin.factory.fruit;
/**
 * 具体工厂类,实现FruitGardener 接口
 */
public class AppleGardener implements FruitGardener {

	@Override
	public Fruit factory() {

		return new Apple();
	}

}

package com.bin.factory.fruit;
/**
 * 抽象产品角色,所有产品继承此类
 *
 */
public interface Fruit {
	void grow();
	void harvest();
	void plant();
}

package com.bin.factory.fruit;
/**
 * 具体产品类苹果
 */
public class Apple implements  Fruit{

	@Override
	public void grow() {
		System.out.print("apple grow");
	}

	@Override
	public void harvest() {
		System.out.print("apple harvest");
	}

	@Override
	public void plant() {
		System.out.print("apple plant");
	}

}

package com.bin.factory.fruit;
/**
 * 客户端
 */
public class Client {

	public static void main(String[] args){
	FruitGardener apple=new AppleGardener();
	Fruit p =apple.factory();
	p.grow();
	}
}

    如果具体工厂角色具有共同的逻辑,那么都可以移动到抽象工厂角色中,那么就可以用JAVA抽象类实现,由抽象工厂类,提供公用的工厂方法,相反的,就可以用一个JAVA接口实现。

   抽象工厂可以规定出多于一个的工厂方法,而是具体工厂具有多种工厂方法。



你可能感兴趣的:(学习《java与模式》 之 工厂模式)