工厂模式
描述:
- 定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
使用场景:
- 消费者不关心它所要创建对象的类(产品类)的时候。
- 消费者知道它所要创建对象的类(产品类),但不关心如何创建的时候···等等。
- 应用场景举例:
1、您需要一辆汽车,可以直接从工厂里面提货,而不用去管这辆汽车是怎么做出来的,以及这个汽车里面的具体实现。
2、日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。
3、数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。
优点:
- 一个调用者想创建一个对象,只要知道其名称就可以了。
- 扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。
- 屏蔽产品的具体实现,调用者只关心产品的接口。
缺点:
- 每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。
一、简单工厂模式(静态工厂模式)
例子如下:
Animal类:
package com.bean;
/**
* 动物类
* @author Lyon Yao
*
*/
public abstract class Animal {
private String name;
public Animal() {
super();
// TODO Auto-generated constructor stub
}
public Animal(String name) {
super();
this.name = name;
}
public abstract void eat();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
猫类:
package com.bean;
/**
* 猫类
* @author Lyon Yao
*
*/
public class Cat extends Animal {
public Cat() {
// TODO Auto-generated constructor stub
}
public Cat(String name) {
super(name);
// TODO Auto-generated constructor stub
}
@Override
public void eat() {
// TODO Auto-generated method stub
System.out.println("I like to eat fish!");
}
}
狗类:
/**
* 狗类
* @author Lyon Yao
*
*/
public class Dog extends Animal {
public Dog() {
// TODO Auto-generated constructor stub
}
public Dog(String name) {
super(name);
// TODO Auto-generated constructor stub
}
@Override
public void eat() {
// TODO Auto-generated method stub
System.out.println("I like to eat bone!");
}
}
静态工厂类:
package com.factory.sta;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
* 静态工厂创建一个对象 静态工厂类产生的对象一般都有共同的特性,继承某一类,或者引用接口之类,在此
* 没有看似没有,但不可否认他们都是Object或者Object的一个子类
* @author Lyon Yao
*
*/
public class StaticFatory {
public static Object getInstance(String className){
Object instance=null;
try {
Class cls=Class.forName(className);
instance= cls.newInstance();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return instance;
}
public static Object getInstance(String className,Object ...agrs) {
Class cls=null;
try {
cls = Class.forName(className);
} catch (ClassNotFoundException e1) {
// TODO Auto-generated catch block
return null;
}
Constructor[] constructors = cls.getConstructors();
Object instance=null;
for(Constructor cons:constructors){
Class <?>[] clses=cons.getParameterTypes();
if(clses.length>0){
boolean isThisConstructor=true;
for(int i=0;i<clses.length;i++){
Class c=clses[i];
if(! c.isInstance(agrs[i]) ){
isThisConstructor=false;
}
}
if(isThisConstructor){
try {
instance=cons.newInstance(agrs);
break;
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else{
continue;
}
}
}
return instance;
}
}
二、工厂方法模式:
其主要是对各个类型的东西分类生产,但分类生产的对象仍然是具有某一特性的。譬如说:前面的静态工厂类是一个综合造车工厂,不管是汽车还是火车都能生产,而工厂方法模式就是工厂具体分工,造汽车的工厂只造汽车,造火车的只造火车,不管造汽车还是火车但造出来的还是车。
具体代码例子如下:(这里的例子和上面的例子是一起的,狗生好多小狗,猫生好多小猫的例子,如果不具体那么是母动物都能生的)
母动物接口:
package com.factory;
import com.bean.Animal;
/**
* 母亲接口
* @author Lyon
*
*/
public interface AnimalMother {
/**
* 生育动物
* @return
*/
public Animal giveBirth();
}
母狗类:
package com.factory.impl;
import com.bean.Animal;
import com.bean.Dog;
import com.factory.AnimalMother;
/**
* 狗母亲 生狗
* @author Lyon Yao
*
*/
public class DogMother implements AnimalMother {
@Override
public Animal giveBirth() {
// TODO Auto-generated method stub
Animal dog=new Dog();
System.out.println("狗母亲生了一只小狗");
return dog;
}
}
母猫类:
package com.factory.impl;
import com.bean.Animal;
import com.bean.Cat;
import com.factory.AnimalMother;
/**
* 猫母亲 生猫咪
* @author Lyon Yao
*
*/
public class CatMother implements AnimalMother {
@Override
public Animal giveBirth() {
// TODO Auto-generated method stub
Animal cat=new Cat();
System.out.println("猫母亲生了一只小猫眯");
return cat;
}
}
三、抽象工厂模式:
- 前面工厂方法模式是比较具体的,是猫肯定生的是小猫,这是不会有问题的,是具体的,那么抽象工厂它所产生的就不是那么具体,产生的对象可能是没有共同特性的。譬如说 一只奶羊不仅仅能够生小羊,同时也能生产羊奶,但小羊是动物,羊奶是食物。
例子如下:
总工厂:
package com.factory;
import com.bean.Milk;
/**
* 能产奶的 动物母亲
* 这里继承 AnimalMother 实现 生育小动物 产奶在此接口声明 构成抽象工厂总接口
* @author Lyon Yao
*
*/
public interface MilkAnimalMother extends AnimalMother {
/**
* 产奶
* @return
*/
public Milk produceMilk();
}
奶羊:
package com.factory.impl;
import com.bean.Animal;
import com.bean.Milk;
import com.bean.Sheep;
import com.bean.SheepMilk;
import com.factory.MilkAnimalMother;
/**
* 奶羊
* @author Lyon Yao
*
*/
public class SheepMilkMother implements MilkAnimalMother{
@Override
public Animal giveBirth() {
// TODO Auto-generated method stub
Animal sheep=new Sheep();
System.out.println("奶羊生了一只小羊");
return sheep;
}
@Override
public Milk produceMilk() {
// TODO Auto-generated method stub
Milk milk=new SheepMilk();
System.out.println("奶羊生产了羊奶");
return milk;
}
}
奶牛:
package com.factory.impl;
import com.bean.Animal;
import com.bean.Cattle;
import com.bean.CattleMile;
import com.bean.Milk;
import com.factory.MilkAnimalMother;
/**
* 奶牛()
* @author Lyon Yao
*
*/
public class CattleMilkMother implements MilkAnimalMother {
@Override
public Animal giveBirth() {
// TODO Auto-generated method stub
Cattle cattle=new Cattle();
System.out.println("奶牛生了一只小牛");
return cattle;
}
@Override
public Milk produceMilk() {
// TODO Auto-generated method stub
Milk milk=new CattleMile();
System.out.println("奶牛生产了牛奶");
return milk;
}
}
下面是测试例子:
package com.test;
import org.junit.Test;
import com.bean.Animal;
import com.bean.Cat;
import com.bean.Dog;
import com.factory.AnimalMother;
import com.factory.MilkAnimalMother;
import com.factory.impl.CatMother;
import com.factory.impl.CattleMilkMother;
import com.factory.impl.DogMother;
import com.factory.impl.SheepMilkMother;
import com.factory.sta.StaticFatory;
/**
* 测试类
*
* @author Lyon Yao
*
*/
public class TestCase {
/**
* 静态工厂类 测试
*/
@Test
public void staticFactoryTest() {
Animal ani1=(Animal) StaticFatory.getInstance(Cat.class.getName());
System.out.println(ani1.getName());
ani1.eat();
ani1=(Animal) StaticFatory.getInstance(Dog.class.getName(),"dog");
System.out.println(ani1.getName());
ani1.eat();
}
/**
* 工厂方法模式测试
*/
@Test
public void methodFactoryTest(){
AnimalMother mother=new CatMother();
mother.giveBirth();
mother=new DogMother();
mother.giveBirth();
}
/**
* 抽象工厂模式测试
*/
@Test
public void abstrFactoryTest(){
MilkAnimalMother mother=new SheepMilkMother();
mother.giveBirth();
mother.produceMilk();
mother=new CattleMilkMother();
mother.giveBirth();
mother.produceMilk();
}
}
控制台输出:
null
I like to eat fish!
dog
I like to eat bone!
猫母亲生了一只小猫眯
狗母亲生了一只小狗
奶羊生了一只小羊
奶羊生产了羊奶
奶牛生了一只小牛
奶牛生产了牛奶