簡單工廠,工廠方法,抽象工廠都屬於設計模式中的創建型模式。其主要功能都是幫助我們把對象的實例化部分抽取了出來,優化了系統的架構,並且增強了系統的擴展性。
大白話
如果簡單工廠是用來生產”東西“的,那任何”東西“的子類,比如汽車,自行車,輪船,洗髮水都是可以被生產的,但此處簡單工廠的壓力太大了啊,任何”東西“的子類都可以被生產,負擔太重,所以一般對簡單工廠類也有種稱呼,叫”上帝類“。
而工廠方法模式就很好的減輕了工廠類的負擔,把某一類/某一種東西交由一個工廠生產,同時增加某一類”東西“並不需要修改工廠類,只需要添加生產這類”東西“的工廠即可,使得工廠類符合開放-封閉原則。
對於”東西“的分類,有時候不能光是橫向的分類,從另一個角度也是可以分類的,不知道這句話的意思能不能懂,打個比方:汽車可以根據品牌分爲奔馳、奧迪,也可以根據類別分爲普通三廂車和SUV車,如果用工廠方法來描述的話,奔馳車工廠有一個方法即生產奔馳車,奧迪車工廠有一個方法生產奧迪車,但在有多重分類的情形下,這樣寫已經不夠用,不符合實際了,這個時候需要用到抽象工廠模式,即奧迪車工廠有兩個方法,一個方法是生產普通三廂奧迪車,另一個方法是生產SUV奧迪車。奔馳車工廠有兩個方法,一個方法是生產普通三廂奔馳車,另一個方法是生產SUV奔馳車。
上面即工廠方法模式和抽象工廠模式的應用場景,因爲這兩者很像,所以概念上不容易區分,可以這麼說,工廠方法模式是一種極端情況的抽象工廠模式,而抽象工廠模式可以看成是工廠方法模式的一種推廣。
再說下抽象工廠模式,此處的抽象工廠接口應該是有兩個方法,一個是生成普通三廂車,一個是生產SUV車,可以說,生產的”東西“已經被限定住了,因此你不能生產某品牌汽車外的其他”東西“,因而可以理解成使用抽象工廠模式不能新增新的”東西“(在簡單工廠和工廠方法中理論上都是可以新增任意”東西“的)。
簡單工廠
簡單工廠模式的工廠類一般是使用靜態方法,通過接收的參數的不同來返回不同的對象實例。不修改代碼的話,是無法擴展的。
簡單工廠代碼示例:
public interface Product{
}
public class ProductA implements Product{
public ProductA(){
System.out.println("生產ProductA ...");
}
}
public class ProductB implements Product{
public ProductB(){
System.out.println("生產ProductB ...");
}
}
public class ProductC implements Product{
public ProductC(){
System.out.println("生產ProductC ...");
}
}
public class SimpleFactory{
public Product getProduct(String name){
if(name.equals("A")){
return new ProductA();
}
else if(name.equals("B")){
return new ProductB();
}
return new ProductC();
}
}
//測試類
public class FactoryTest {
public static void main(String[] args) {
//廠商1負責生產產品A1、B1
SimpleFactory sf = new SimpleFactory();
Product p1= sf.getProduct("A");
Product p2 = sf.getProduct("B");
}
}
工廠方法
工廠方法是針對每一種產品提供一個工廠類。通過不同的工廠實例來創建不同的產品實例。在同一等級結構中,支持增加任意產品。
工廠方法代碼示例:
public interface Product{
}
public interface Creator{
public Product factory();
}
public class ConcreteProduct1 implements Product{
public ConcreteProduct1(){
System.out.println("ConcreteProduct1被創建");
}
}
public class ConcreteProduct2 implements Product{
public ConcreteProduct2(){
System.out.println("ConcreteProduct2被創建");
}
}
public class ConcreteCreator1 implements Creator{
public Product factory(){
return new ConcreteProduct1();
}
}
public class ConcreteCreator2 implements Creator{
public Product factory(){
return new ConcreteProduct2();
}
}
public class FactoryTest{
private static Creator creator1, creator2;
private static Product prod1, prod2;
public static void main(String[] args){
creator1 = new ConcreteCreator1();
prod1 = creator1.factory();
System.out.println("----------------------------");
creator2 = new ConcreteCreator2();
prod2 = creator2.factory();
}
}
抽象工廠
抽象工廠是應對產品族概念的。比如說,每個汽車公司可能要同時生產轎車,貨車,客車,那麼每一個工廠都要有創建轎車,貨車和客車的方法。
應對產品族概念而生,增加新的產品線很容易,但是無法增加新的產品。
抽象工廠代碼示例:
public interface IProductA{
public void method();
}
public interface IProductB{
public void method();
}
//由於已經設計好A1由廠商1生產,故以下輸出代碼有“廠商x”
public class ProductA1 implements IProductA{
public void method() {
System.out.println("廠商1 生產ProductA1 ...");
}
}
public class ProductA2 implements IProductA{
public void method() {
System.out.println("廠商2 生產ProductA2 ...");
}
}
public class ProductB1 implements IProductB{
public void method() {
System.out.println("廠商1 生產ProductB1 ...");
}
}
public class ProductB2 implements IProductB{
public void method() {
System.out.println("廠商2 生產ProductB2 ...");
}
}
//不同的廠商負責自己牌子產品的生產
public abstract class Factory1{
abstract IProductA getProductA1();
abstract IProductB getProductB1();
}
public abstract class Factory2{
abstract IProductA getProductA2();
abstract IProductB getProductB2();
}
//具體的工廠用來生產相關的產品
public class ConcreteFactory1 extends Factory1{
public IProductA getProductA1() {
return new ProductA1();
}
public IProductB getProductB1() {
return new ProductB1();
}
}
public class ConcreteFactoryB extends Factory2{
public IProductA getProductA2() {
return new ProductA2();
}
public IProductB getProductB2() {
return new ProductB2();
}
}
//測試類
public class FactoryTest {
public static void main(String[] args) {
//廠商1負責生產產品A1、B1
Factory1 factory1 = new ConcreteFactory1();
IProductA productA1 = factory1.getProductA1();
IProductB productB1 = factory1.getProductB1();
productA1.method();
productB1.method();
//廠商2負責生產產品A2、B2
Factory2 factory2 = new ConcreteFactoryB();
IProductA productA2 = factory2.getProductA2();
IProductB productB2 = factory2.getProductB2();
productA2.method();
productB2.method();
}
}
三者的區別
簡單工廠 : 用來生產同一等級結構中的任意產品。(在遵循開閉原則的條件下,對於增加新的產品,無能爲力)。
工廠方法 :用來生產同一等級結構中的固定產品。(支持增加任意產品) 。
抽象工廠 :用來生產不同產品族的全部產品。(對於增加新的產品,無能爲力;支持增加產品族) 。
總結
工廠模式中,重要的是工廠類,而不是產品類。產品類可以是多種形式,多層繼承或者是單個類都是可以的。但要明確的,工廠模式的接口只會返回一種類型的實例,這是在設計產品類的時候需要注意的,最好是有父類或者共同實現的接口。使用工廠模式,返回的實例一定是工廠創建的,而不是從其他對象中獲取的。工廠模式返回的實例可以不是新創建的,返回由工廠創建好的實例也是可以的。
原文地址:http://blog.csdn.net/superbeck/article/details/4446177#comments
http://www.cnblogs.com/devinzhang/archive/2011/12/19/2293160.html