1. 程式人生 > >003 工廠方法模式

003 工廠方法模式

nfa 函數 new 問題 strac gpo 密碼 xtend blog

一 .說一說

在簡單工廠之中,我們的最終演化的過程中,有一個很煩的問題就是當增加產品的時候,我們的枚舉類會不斷的修改.

雖然修改在一定程度上我們能保證不出問題,但這依然不夠優雅.


二 .工廠演進

提供一個生產槍的工廠接口.

public interface GunFactory {
    Gun productGun();
}

子類:

public class AK47GunFactory implements GunFactory {
    @Override
    public Gun productGun() {
        return new AK47();
    }
}
public class B11GunFactory implements GunFactory{
    @Override
    public Gun productGun() {
        return new B11();
    }
}

客戶端:

public static void main(String[] args) {
        Gun gun = new AK47GunFactory().productGun();
        gun.shot();
    }

現在我們如果要擴展槍的話,就可以擴展工廠和對應的槍了.

我們能夠保證代碼符合開閉原則的.


問題的出現:

每次出現新槍,客戶端雖然代碼不用變化,但是客戶端在一定程度上需要知道自己需要什麽樣的槍工廠.

我們來回憶一下使用工廠的好處,就是獲得創建對象時細節的控制權.

從這一點上講,使用工廠比直接使用構造函數好.

這就是我們使用工廠最直接的原因.[可以獲得創建對象細節的權利].


看下面的情景:

我需要使用槍來打鳥.

public abstract class  ShotBird {
    protected abstract Gun getGun() ;
    public void shotBird() {
        getGun().shot();
        System.out.println(
"鳥被打死了!!"); } }

現在我們需要使用ak47打鳥.

public class Ak47ShotBird extends ShotBird {
    @Override
    protected Gun getGun() {
        return new AK47();
    }
}

客戶端:

public static void main(String[] args) {
        ShotBird shot = new Ak47ShotBird();
        shot.shotBird();
    }

我們每次選用不同的槍來打鳥,只需要實現以下工廠方法就好了.有了槍,怎麽打鳥的代碼就可以復用了.

這也就是說,我們除了創建槍的代碼不能復用,其它的代碼都能復用.


工廠方法模式:

定義定義創建對象的方法[對象--一般以接口的形式表示],讓子類完成該方法.父類可以將其他代碼進行復用.

也就是說,工廠方法模式創建的對象一般不是給客戶端使用的,是給父類的內部代碼使用的.


現在由一個情景:

用戶的登錄過程:

public abstract class Login {
    //獲得一個匹配器
    protected abstract Matcher getMatcher();
    //實現登錄
    public boolean login(String username , String password) {
        Matcher matcher = getMatcher();
        return matcher.check(username,password);
    }
}

現在登錄的方式有很多,比如使用MD5加密之後再登錄.

//匹配器
public interface Matcher {
    //通過賬號和密碼進行匹配
    Boolean check(String username, String password);
}
public class MD5Matcher implements Matcher {
    @Override
    public Boolean check(String username, String password) {
        System.out.println("通過賬號"+username +"和密碼"+password +"進行驗證");
        //省略大量驗證代碼
        return Boolean.TRUE;
    }
}

實現一個MD5登錄.

public class MD5Login extends Login {
    @Override
    protected Matcher getMatcher() {
        return new MD5Matcher();
    }
}

客戶端代碼:

    public static void main(String[] args) {
        Login login = new MD5Login();
        login.login("trek", "123456");
    }

通過上面的例子,我們現在應該能理解工廠方法模式了.

工廠方法模式創建的對象一般都是給內部使用的,目的是為了復用其它的代碼,比如登錄登錄時可以記錄日誌啊等操作.

從這一點上講,和簡單工廠根本不是一個方向上的模式.

我看了一些資料,覺的那些資料上應該是片面的理解了這個模式.

最終我是按照淹沒設計模式的方向去理解這個模式的.


003 工廠方法模式