工廠模式
描述:
- 定義一個創建對象的接口,讓其子類自己決定實例化哪一個工廠類,工廠模式使其創建過程延遲到子類進行。
使用場景:
- 消費者不關心它所要創建對象的類(產品類)的時候。
- 消費者知道它所要創建對象的類(產品類),但不關心如何創建的時候···等等。
- 應用場景舉例:
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!
貓母親生了一隻小貓眯
狗母親生了一隻小狗
奶羊生了一隻小羊
奶羊生產了羊奶
奶牛生了一隻小牛
奶牛生產了牛奶