1. 程式人生 > >設計模式之禪(4)-工廠模式

設計模式之禪(4)-工廠模式

文章目錄


更多關於設計模式的文章請點選設計模式之禪(0)-目錄頁


工廠模式(Factory Pattern)是 Java 中最常用的設計模式之一。這種型別的設計模式屬於建立型模式,它提供了一種建立物件的最佳方式。

一、簡單工廠模式

1.1、單一new方式

我們在開發專案時如果需要獲取物件,通常會使用單一new的方式去獲取它:

	Object object1 = new Object1();
	Object object2 = new Object2();
	Object object3 = new Object3();

我們或許還會在創建出來後進行一些處理:

	Object object1 = new Object1();
	object1.setA(A);
	object1.setB(B);
	Object object2 = new Object2();
	object2.
setA(A); object2.setB(B); Object object3 = new Object3(); object3.setA(A); object3.setB(B);

這會暴露出一個問題:
所有的建立過程和固定的操作都需要寫出來,並且在原生代碼中將其暴露。這不符合寫入不變的、封裝變化的程式碼的設計模式,所以說,我們需要一個類似於工廠的角色去產生這些物件,並且對它們進行一些固定的操作。這樣就自然而然地引出了簡單工廠模式(Simple Factory Pattern)。

1.2、簡單工廠模式

簡單工廠模式(Simple Factory Pattern)的使用很簡單,再拿我們的動物簡單工廠來舉例子:

public class SimpleAnimalFactory{
    public Animal getAnimal(String type){
        if(type.equals("Dog")){
      		Animal dog =  new Dog();
      		//處理dog
            return  dog ;
        }else if(type.equals("Cat")){
            Animal cat=  new Cat();
      		//處理cat
            return  cat;
        }
    }
}

當我們需要Dog時,只需要建立SimpleAnimalFactory,再用其呼叫getAnimal(“Dog”)即可獲得一隻"經過處理的狗",而且這些建立和處理對"呼叫者"來說是"不可見"的,呼叫者並不在乎工廠內部到底做了什麼,只需要獲得經過處理的物件。

那麼,工廠模式就這樣講完了嗎?當然不是。其實,簡單工廠模式並不算是一種設計模式,工廠模式也遠沒那麼簡單。

二、抽象工廠及工廠方法

2.1、將簡單工廠改造成抽象工廠

在上面的簡單工廠中,我們所實現的SimpleAnimalFactory已經能幫助我們獲得簡單的動物了,但是當我們需要動物園的動物時,我們需要製造一個ZooAnimalFactory;同理,當我們需要野生動物時,我們需要WildAnimalFactory,我們可以這樣寫:

  • ZooAnimalFactory
public class ZooAnimalFactory{
  
    public Animal getAnimal(String type) {
        if(type.equals("ZooDog")){
            return new ZooDog();
        }else if(type.equals("ZooCat")){
            return  new ZooCat();
        }
        return null;
    }
}
  • WildAnimalFactory
public class WildAnimalFactory{
   
    public Animal getAnimal(String type) {
        if(type.equals("WildDog")){
            return new WildDog();
        }else if(type.equals("WildCat")){
            return  new WildCat();
        }
        return null;
    }
}

如果你需要其他各種各樣的工廠,我們只能一遍又一遍地寫著,那麼為什麼我們不能抽取出來一個動物工廠超類,讓其他工廠去繼承它,獲得工廠所需的方法和屬性呢?這就是抽象工廠:

  • AnimalFactory
public abstract class AnimalFactory {
    public abstract Animal getAnimal(String type);
    }
}

此時,我們的ZooAnimalFactory和WildAnimalFactory可以這樣寫:

  • ZooAnimalFactory
public class ZooAnimalFactory extends AnimalFactory{
  	@Override
    public Animal getAnimal(String type) {
        if(type.equals("ZooDog")){
            return new ZooDog();
        }else if(type.equals("ZooCat")){
            return  new ZooCat();
        }
        return null;
    }
}
  • WildAnimalFactory
public class WildAnimalFactory extends AnimalFactory{
   @Override
    public Animal getAnimal(String type) {
        if(type.equals("WildDog")){
            return new WildDog();
        }else if(type.equals("WildCat")){
            return  new WildCat();
        }
        return null;
    }
}

2.2、為抽象工廠中添加工廠方法

我們上面的抽象工廠已經可以滿足基本的需求了,但是還有一點美中不足:工廠中的動物由getAnimal(String type)方法建立,這裡頭真正產生動物的程式碼沒有被封裝起來,這就是所謂的工廠方法,即真正產生出物件的方法,我們可以在抽象工廠中新增一個工廠方法createAnimal(String type),並且讓子類去重寫這個工廠方法。

  • AnimalFactory
/**
 * @Auther: ARong
 * @Date: 2018/11/25 19:34
 * @Description: 動物工廠超類
 */
public abstract class AnimalFactory {

    public Animal getAnimal(String type){
        //呼叫createAnimal方法,該方法由實現類去重寫
        Animal animal = createAnimal(type);
        return animal;
    }

    protected abstract Animal createAnimal(String type);
}

三、工廠模式總結

以上工廠模式的類,可以用簡單的UML關係圖來表示:
在這裡插入圖片描述

  • AnimalFactory
/**
 * @Auther: ARong
 * @Date: 2018/11/25 19:34
 * @Description: 動物工廠超類
 */
public abstract class AnimalFactory {

    public Animal getAnimal(String type){
        //呼叫createAnimal方法,該方法由實現類去重寫
        Animal animal = createAnimal(type);
        return animal;
    }

    protected abstract Animal createAnimal(String type);
}
  • ZooAnimalFactory
/**
 * @Auther: ARong
 * @Date: 2018/11/25 19:36
 * @Description: AnimalFactory的實現類
 */
public class ZooAnimalFactory extends AnimalFactory{


    //按需重寫createAnimal方法
    @Override
    protected Animal createAnimal(String type) {

        if(type.equals("ZooDog")){
            return new ZooDog();
        }else if(type.equals("ZooCat")){
            return  new ZooCat();
        }

        return null;
    }
}
  • WildAnimalFactory
/**
 * @Auther: ARong
 * @Date: 2018/11/25 19:41
 * @Description: AnimalFactory的實現類,野生動物工廠
 */
public class WildAnimalFactory extends AnimalFactory{
    @Override
    protected Animal createAnimal(String type) {

        if(type.equals("WildDog")){
            return new WildDog();
        }else if(type.equals("WildCat")){
            return  new WildCat();
        }


        return null;
    }
}
  • Animal
/**
 * @Auther: ARong
 * @Date: 2018/11/17 11:08
 * @Description:動物的抽象類,定義動物的屬性以及抽象行為和具體行為
 */
public abstract class Animal {
    //動物名稱
    private String name;
    //定義run方法
    public abstract  void run();

    //get、set
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
  • ZooCat/ZooDog/WildCat/WildDog的程式碼不列出了

  • 測試

/**
 * @Auther: ARong
 * @Date: 2018/11/25 19:44
 * @Description: 動物工廠測試
 */
public class TestAnimalFactory {


    @Test
    public void getZooAnimal(){
        AnimalFactory zooAnimalFactory = new ZooAnimalFactory();
        Animal zooDog = zooAnimalFactory.getAnimal("ZooDog");
        zooDog.run();
    }


    @Test
    public void getWildAnimal(){
       AnimalFactory wildAnimalFactory = new WildAnimalFactory();
        Animal wildCat = wildAnimalFactory.getAnimal("WildCat");
        wildCat.run();
    }

}