GOF23(2)之工廠模式(創建型模式)

工廠模式的主要作用:實現了創建者和調用者的分離。

工廠模式的核心本質:實例化對象,用工廠方法代替new操作;將選擇實現類、創建對象統一管理和控制。從而將調用者和我們的實現類進行解耦。

詳細可以分爲:

       簡單工廠模式:用來生產同一等級結構中的任意產品。(對於增加新的產品,需要修改原來的代碼)

       工廠方法模式:用來生產同一等級結構中的固定產品。(支持增加任意產品,不需要修改已有代碼)

       抽象工廠模式:用來生產不同產品族的全部產品。(對於增加新的產品無能爲力,支持增加產品族)

面向對象設計的基本原則:

1 OCP 開閉原則(Open Closed Principle):一個軟件的實體應該對擴展開放,對修改關閉;

2 DIP 依賴倒轉原則(Dependence Inversion Principle):要針對接口編程,不要針對實現編程;

3 LoD 迪米特法則(Law of Demeter):只與你直接的朋友通信,避免和陌生人通信。

 

1、簡單工廠模式

1.1 創建接口

package com.zdw.factory.simpleFactory;

public interface Car {
    void run();
}

1.2 創建兩個實現類

1.2.1 奧迪車

package com.zdw.factory.simpleFactory;

public class Audi implements Car {
    @Override
    public void run() {
        System.out.println("我是一輛奧迪車,我百公里加速8秒");
    }
}

1.2.2 吉利車

package com.zdw.factory.simpleFactory;

public class JiLi implements Car {
    @Override
    public void run() {
        System.out.println("我是一輛吉利車,我百公里加速10秒");
    }
}

1.3 創建工廠類

通過工廠類來創建不同的實現類對象:

package com.zdw.factory.simpleFactory;

/**
 * 簡單工廠類,通過參數來創建不同的實現對象
 */
public class CarFactory {
    public static Car createCar(String type){
        if("奧迪".equals(type)){
            return new Audi();
        }else if("吉利".equals(type)){
            return new JiLi();
        }else {
            return null;
        }
    }
}

1.4 測試

package com.zdw.factory.simpleFactory;

public class TestSimpleFactory {
    public static void main(String[] args) {
        Car audi = CarFactory.createCar("奧迪");
        Car jiLi = CarFactory.createCar("吉利");
        audi.run();
        jiLi.run();
    }
}

1.5 要點

1、簡單工廠模式也叫靜態工廠模式,因爲一般工廠類的方法都是靜態方法,通過類名直接調用;

2、對於增加新產品,就必須要修改已有代碼。

2、工廠方法模式

簡單工廠模式不能完全滿足OCP開閉原則,而工廠方法模式可以解決這個問題;

工廠方法模式和簡單工廠模式最大的不同在於:簡單工廠模式只有一個工廠類(對於一個小項目或一個模塊而言),而工廠方法模式有一組實現了相同接口的工廠類。

2.1 創建接口和實現類

我們創建的Car接口及其兩個實現類Audi和JiLi是跟上面的簡單工廠模式的是一樣的代碼,這裏不再贅述。

2.2 創建工廠接口和工廠實現

2.2.1 創建工廠接口

工廠接口中有一個方法,方法的作用是用來創建Car對象;

package com.zdw.factory.factoryMethod;

/**
 * 工廠方法的接口
 */
public interface CarFactory {
    Car createCar();
}

2.2.2 創建工廠實現類

奧迪車的工廠類

package com.zdw.factory.factoryMethod;

public class AudiFactory implements CarFactory {
    @Override
    public Car createCar() {
        return new Audi();
    }
}

吉利車的工廠類

package com.zdw.factory.factoryMethod;

public class JiLiFactory implements CarFactory {
    @Override
    public Car createCar() {
        return new JiLi();
    }
}

2.3 測試

package com.zdw.factory.factoryMethod;

public class TestFactoryMethod {
    public static void main(String[] args) {
        Car audi = new AudiFactory().createCar();
        Car jiLi = new JiLiFactory().createCar();
        audi.run();
        jiLi.run();
    }
}

現在如果我們需要新增一個產品奔馳車,那麼我們不需要修改之前的代碼,只要新增一個BenChi類實現Car接口,通過新增一個BenChiFactory實現CarFactory工廠接口。這樣就滿足了OCP開閉原則了。但是它會新增很多的類,會變得複雜,所以其實項目中簡單工廠模式是用的比較多的。

3、抽象工廠模式

抽象工廠模式用來生產不同產品族的全部產品。對於增加新的產品,無能爲力,但是支持新增新的產品族。

抽象工廠模式是工廠方法模式的升級版,在有多個業務品種,業務分類時,通過抽象工廠生產需要的對象是一種非常好的解決方式。

下面我們還是以Car作爲例子,假設Car是由三個主要的部件組成的:發動機,輪胎和座椅。不同等級的部件可以生產出不同的Car。

3.1 創建發動機及其實現

package com.zdw.factory.abstractFactory;

public interface Engine {
    void run();
}

//高端發動機
class LuxuryEngine implements Engine{

    @Override
    public void run() {
        System.out.println("高端發動機,轉速快,噪聲小");
    }
}

//低端發動機
class LowEngine implements Engine{

    @Override
    public void run() {
        System.out.println("低端發動機,轉速慢,噪聲好大好大。。。");
    }
}

3.2 創建輪胎接口及其實現

package com.zdw.factory.abstractFactory;

public interface Tyre {
    void revolve();
}

//高端輪胎
class LuxuryTyre implements Tyre{

    @Override
    public void revolve() {
        System.out.println("高端輪胎,耐磨");
    }
}

//低端輪胎
class LowTyre implements Tyre{

    @Override
    public void revolve() {
        System.out.println("低端輪胎,不經磨,經常破。。。");
    }
}

3.3 創建座椅接口及其實現

package com.zdw.factory.abstractFactory;

public interface Seat {
    void massage();
}

class LuxurySeat implements Seat{

    @Override
    public void massage() {
        System.out.println("高端座椅可以自動按摩的,很舒服");
    }
}

class LowSeat implements Seat{

    @Override
    public void massage() {
        System.out.println("低端座椅不能按摩,坐久了屁股痛。。。。");
    }
}

3.4 創建生產Car的工廠接口及其實現

3.4.1 Car工廠接口

package com.zdw.factory.abstractFactory;

/**
 * 生產車子的工廠接口
 */
public interface CarFactory {
    Engine createEngine();
    Tyre createTyre();
    Seat createSeat();
}

3.4.2 高端車子的工廠類

package com.zdw.factory.abstractFactory;

public class LuxuryCarFactory implements CarFactory {
    @Override
    public Engine createEngine() {
        return new LuxuryEngine();//生產高端發動機
    }

    @Override
    public Tyre createTyre() {
        return new LuxuryTyre();//生產高端輪胎
    }

    @Override
    public Seat createSeat() {
        return new LuxurySeat();//生產高端座椅
    }
}

3.4.3 低端車子的工廠類

package com.zdw.factory.abstractFactory;

public class LowCarFactory implements CarFactory {
    @Override
    public Engine createEngine() {
        return new LowEngine();//生產低端發動機
    }

    @Override
    public Tyre createTyre() {
        return new LowTyre();//生產低端輪胎
    }

    @Override
    public Seat createSeat() {
        return new LowSeat();//生產低端座椅
    }
}

 

3.5 測試

package com.zdw.factory.abstractFactory;

public class TestAbstractFactory {
    public static void main(String[] args) {
        CarFactory carFactory = new LuxuryCarFactory();
        Engine engine = carFactory.createEngine();
        Tyre tyre = carFactory.createTyre();
        Seat seat = carFactory.createSeat();
        engine.run();
        tyre.revolve();
        seat.massage();
    }
}

這樣我們通過不能的工廠實現類,就能創建不同的車子了。

 

3.6 抽象工廠的應用場景

JDK中的Calendar的getInstance方法;

JDBC中的Connection對象的獲取;

Hibernate中的SessionFactory創建Session;

Spring的IoC容器創建的管理的Bean對象;

反射Class對象的newInstance方法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章