1. 程式人生 > >詳解設計模式 - 工廠模式(3種)

詳解設計模式 - 工廠模式(3種)


這篇文章作為個人學習備忘筆記,通過生活中的牛奶工廠例項,比對3種工廠模式的不同。

工廠模式一句話總結:

只對生產結果負責,不要三無產品。

生活中的工廠例子

  • 小作坊:五花八門什麼都能生產,但生產質量和產品種類不一定滿足消費者的需求。
  • 專業工廠:遵循一定標準,不生產其他產品,只專注於自己的產品,不斷精益求精。
  • 大型國際工廠:專業、高效,無論是產品質量還是產品種類,都能讓使用者放心。

以上這三種工廠,對應到設計模式中分別就是:簡單工廠模式工廠方法模式抽象工廠模式

牛奶工廠案例

有三種牛奶:蒙牛、伊利、特侖蘇,現在分不同的工廠去生產。

牛奶(它是一個抽象的東西)
/**
 * 牛奶
 *
 * @author Zebe
 */
public interface Milk {

    /**
     * 牛奶名稱
     * @return 返回牛奶名稱
     */
    String getName();

}
蒙牛
/**
 * 蒙牛牛奶
 *
 * @author Zebe
 */
public class MengNiu implements Milk {

    @Override
    public String getName() {
        return "蒙牛";
    }
}
伊利
/**
 * 伊利牛奶
 *
 * @author Zebe
 */
public class YiLi implements Milk {

    @Override
    public String getName() {
        return "伊利";
    }
}
特侖蘇
/**
 * 特侖蘇牛奶
 *
 * @author Zebe
 */
public class TeLunSu implements Milk {

    @Override
    public String getName() {
        return "特侖蘇";
} }

簡單工廠模式的做法

使用者要什麼就給什麼,如果自己沒有的,就給不了。

/**
 * 簡單工廠(很少使用)
 *
 * 說明:這是簡單工廠模式(根據使用者要求來,不一定完全滿足使用者的需要)
 *
 * @author Zebe
 */
public class SimpleFactory {

    /**
     * 生產牛奶
     * @param name 牛奶名稱
     * @return 根據牛奶名稱返回具體的牛奶
     */
    Milk getMilk(String name) {
        if ("蒙牛".equals(name)) {
            return new MengNiu();
        } else if ("伊利".equals(name)) {
            return new YiLi();
        } else if ("特侖蘇".equals(name)) {
            return new TeLunSu();
        } else {
            // 如果要新增加一種牛奶,必須修改這裡的程式碼實現
            System.out.println("無法生成指定的牛奶:" + name);
            return null;
        }
    }

}
使用測試
/**
 * 簡單工廠使用測試
 *
 * @author Zebe
 */
public class SimpleFactoryTest {

    /**
     * 程式入口
     * @param args 執行引數
     */
    public static void main(String[] args) {
        SimpleFactory factory = new SimpleFactory();
        // 這裡如果名稱傳錯,會得不到想要的牛奶
        System.out.println(factory.getMilk("蒙牛"));
    }

}

工廠方法模式的做法

指定一個協議(標準),所有牛奶工廠都要遵循這個協議來生產。

/**
 * 牛奶工廠(更加專業,不同的工廠只生產指定的牛奶)
 *
 * 說明:這是工廠方法模式(相當於制定一個加工協議或者標準,其他的牛奶工廠都要按照這個協議去實現)
 *
 * @author Zebe
 */
public interface SpecificMilkFactory {

    /**
     * 生產牛奶(這是一個協議)
     * @return 返回牛奶
     */
    Milk getMilk();

}
蒙牛工廠(按協議來生產)
/**
 * 蒙牛工廠(只專注於生產蒙牛牛奶)
 *
 * @author Zebe
 */
public class MengNiuFactory implements SpecificMilkFactory {

    @Override
    public Milk getMilk() {
        return new MengNiu();
    }
}
伊利工廠(按協議來生產)
/**
 * 伊利工廠(只專注於生產伊利牛奶)
 *
 * @author Zebe
 */
public class YiLiFactory implements SpecificMilkFactory {

    @Override
    public Milk getMilk() {
        return new YiLi();
    }
}

特侖蘇工廠(按協議來生產)
/**
 * 特侖蘇工廠(只專注於生產特侖蘇牛奶)
 *
 * @author Zebe
 */
public class TeLunSuFactory implements SpecificMilkFactory {

    @Override
    public Milk getMilk() {
        return new TeLunSu();
    }
}
使用測試
/**
 * 牛奶工廠測試
 *
 * @author Zebe
 */
public class SpecificMilkFactoryTest {

    /**
     * 執行入口
     *
     * @param args 執行引數
     */
    public static void main(String[] args) {
        // 要什麼牛奶,就需要指定具體某個專業的牛奶工廠
        SpecificMilkFactory factory = new MengNiuFactory();
        System.out.println(factory.getMilk());
    }

}

抽象工廠模式的做法

更專業、質量更高,對於生產的產品有明確規範,除了能自己生產,還可以委派給其他專業的牛奶工廠生產(國內或者國外都行)。

/**
 * 牛奶工廠(高階流水線工廠)
 * 說明:這是抽象工廠模式(把所有能生產的牛奶抽象出來)
 *
 * @author Zebe
 */
public abstract class AbstractMilkFactory {

    /**
     * 生產蒙牛牛奶
     * @return 返回蒙牛牛奶
     */
    abstract Milk getMengNiu();

    /**
     * 生產伊利牛奶
     * @return 返回伊利牛奶
     */
    abstract Milk getYiLi();

    /**
     * 生產特侖蘇牛奶
     * @return 返回特侖蘇牛奶
     */
    abstract Milk getTeLunSu();

}
具體的某某牛奶工廠
/**
 * 某某牛奶工廠(可以生產所有牛奶)
 *
 * @author Zebe
 */
public class XXXMilkFactory extends AbstractMilkFactory {

    @Override
    Milk getMengNiu() {
        // 自己生產
        return new MengNiu();
        // 或委派給專業的蒙牛工廠生產(混用設計模式)
        // return new MengNiuFactory().getMilk();
    }

    @Override
    Milk getYiLi() {
        // 自己生產
        return new YiLi();
        // 或委派給專業的伊利工廠生產(混用設計模式)
        // return new YiLiFactory().getMilk();
    }

    @Override
    Milk getTeLunSu() {
        // 自己生產
        return new TeLunSu();
        // 或委派給專業的特侖蘇工廠生產(混用設計模式)
        // return new TeLunSuFactory().getMilk();
    }
}
使用測試
/**
 * 牛奶工廠測試
 *
 * @author Zebe
 */
public class AbstractMilkFactoryTest {

    /**
     * 執行入口
     *
     * @param args 執行引數
     */
    public static void main(String[] args) {
        XXXMilkFactory factory = new XXXMilkFactory();
        // 使用者想要什麼牛奶,應有盡有
        System.out.println(factory.getMengNiu());
        System.out.println(factory.getYiLi());
        System.out.println(factory.getTeLunSu());
        // 假設這個牛奶工廠出新產品了,例如:莫斯利安
        // 那麼使用者只需要拿錢購買即可(客戶端不做改變),如下:
        // System.out.println(factory.getMoSiLiAn());
    }

}

小結

1、小作坊(簡單工廠模式)明顯不可靠,所以很少使用或者不使用
2、工廠方法模式可以看成就是一個協議(介面),對應所有的具體工廠都要遵循這個協議來進行生產。
3、抽象工廠模式是最可靠的工廠模式,它最大程度地遮蔽了生產細節