設計模式-簡單工廠、工廠方法模式、抽象工廠模式

崔世峰發表於2019-02-26

工廠方法模式

概要

  1. 一個抽象產品類
  2. 多個具體產品類
  3. 一個抽象工廠
  4. 多個具體工廠 - 每一個具體產品對應一個具體工廠
  5. 符合 - OCP開放封閉原則

image

優點

  1. 降低了程式碼耦合度,物件的生成交給子類去完成
  2. 實現了開放封閉原則 - 每次新增子產品 不需要修改原有程式碼

缺點

  1. 增加了程式碼量,每個具體產品都需要一個具體工廠
  2. 當增加抽象產品 也就是新增一個其他產品族 需要修改工廠 違背OCP

程式碼角度進一步解讀

抽象產品類

/**
 * @author cuishifeng
 * @create 2018-08-02
 **/
public interface Computer {

    /**
     * 生產電腦
     */
    void createComputer();
}

複製程式碼

具體產品

/**
 * @author cuishifeng
 * @create 2018-08-02
 **/
public class Cpu implements Computer {

    @Override
    public void createComputer() {
        System.out.println("生產cpu");
    }
}

複製程式碼
/**
 * @author cuishifeng
 * @create 2018-08-02
 **/
public class Disk implements Computer {

    @Override
    public void createComputer() {
        System.out.println("生產磁碟disk");
    }
}

複製程式碼
/**
 * @author cuishifeng
 * @create 2018-08-02
 **/
public class Displayer implements Computer {
    @Override
    public void createComputer() {
        System.out.println("生產顯示卡displayer");
    }
}
複製程式碼

抽象工廠類

/**
 * @author cuishifeng
 * @create 2018-08-02
 **/
public interface ComputerFactory {

    /**
     * 工廠方法模式的抽象工廠
     * @return
     */
     Computer getProduct();
}

複製程式碼

具體工廠

/**
 * @author cuishifeng
 * @create 2018-08-02
 **/
public class CpuFactory implements ComputerFactory {

    @Override
    public Computer getProduct() {
        return new Cpu();
    }
}
複製程式碼
/**
 * @author cuishifeng
 * @create 2018-08-02
 **/
public class DiskFactory implements ComputerFactory{
    @Override
    public Computer getProduct() {
        return new Disk();
    }
}
複製程式碼
/**
 * @author cuishifeng
 * @create 2018-08-02
 **/
public class DisplayerFactory implements ComputerFactory {
    @Override
    public Computer getProduct() {
        return new Displayer();
    }
}
複製程式碼
/**
 * 客戶端
 * @author cuishifeng
 * @create 2018-08-02
 **/
public class AppClient {

    public static void main(String[] args) {
        ComputerFactory computerFactory = new CpuFactory();
        computerFactory.getProduct().createComputer();

        System.out.println("---------------------------- ");

        computerFactory = new DiskFactory();
        computerFactory.getProduct().createComputer();

        System.out.println("---------------------------- ");

        computerFactory = new DisplayerFactory();
        computerFactory.getProduct().createComputer();

    }
}
複製程式碼

列印結果

生產cpu
---------------------------- 
生產磁碟disk
---------------------------- 
生產顯示卡displayer

Process finished with exit code 0
複製程式碼

抽象工廠模式

概要

  1. 多個抽象產品類
  2. 具體產品類
  3. 抽象工廠類 - 宣告(一組)返回抽象產品的方法
  4. 具體工廠類 - 生成(一組)具體產品

image

優點

  1. 程式碼解耦
  2. 實現多個產品族(相關聯產品組成的家族),而工廠方法模式的單個產品,可以滿足更多的生產需求
  3. 很好的滿足OCP開放封閉原則
  4. 抽象工廠模式中我們可以定義實現不止一個介面,一個工廠也可以生成不止一個產品類 對於複雜物件的生產相當靈活易擴充套件

缺點

1.擴充套件產品族相當麻煩 而且擴充套件產品族會違反OCP,因為要修改所有的工廠,例如我們有電腦和滑鼠組成的一個產品族,我們寫完程式碼再去新增一個鍵盤就會很麻煩,看完下面程式碼就會理解了

2.由於抽象工廠模式是工廠方法模式的擴充套件 總體的來說 很笨重

程式碼角度進一步解讀

抽象產品

/**
 * 計算機-抽象產品類
 * @author cuishifeng
 * @create 2018-08-02
 **/
public abstract class Computer {

    /**
     * 生產計算機
     */
    public abstract void productComputer();
}
複製程式碼
/**
 * 滑鼠 - 抽象產品類
 * @author cuishifeng
 * @create 2018-08-02
 **/
public abstract class Mouse {

    /**
     * 生產滑鼠
     */
    public abstract void productMouse();
}
複製程式碼

具體產品

電腦的具體產品

/**
 * PC計算機具體產品類
 * @author cuishifeng
 * @create 2018-08-02
 **/
public class PcComputer extends Computer {

    @Override
    public void productComputer() {
        System.out.println("PC端計算機");
    }
}
複製程式碼
/**
 * @author cuishifeng
 * @create 2018-08-02
 **/
public class ServerComputer extends Computer {

    @Override
    public void productComputer() {
        System.out.println("Server端計算機");
    }
}
複製程式碼

滑鼠具體產品

/**
 * @author cuishifeng
 * @create 2018-08-02
 **/
public class GameMouse extends Mouse {

    @Override
    public void productMouse() {
        System.out.println("遊戲滑鼠");
    }
}
複製程式碼
/**
 * @author cuishifeng
 * @create 2018-08-02
 **/
public class OfficeMouse extends Mouse {

    @Override
    public void productMouse() {
        System.out.println("辦公滑鼠");
    }
}
複製程式碼

抽象工廠

/**
 * @author cuishifeng
 * @create 2018-08-02
 **/
public interface IFactory {

    /**
     * 獲取計算機
     * @return
     */
    Computer getComputer();

    /**
     * 獲取滑鼠
     * @return
     */
    Mouse getMouse();

}

複製程式碼

產品A具體工廠

/**
 * @author cuishifeng
 * @create 2018-08-02
 **/
public class ProductFactoryA implements IFactory {

    @Override
    public Computer getComputer() {
        return new PcComputer();
    }

    @Override
    public Mouse getMouse() {
        return new OfficeMouse();
    }
}
複製程式碼

產品B具體工廠

/**
 * @author cuishifeng
 * @create 2018-08-02
 **/
public class ProductFactoryB implements IFactory {
    @Override
    public Computer getComputer() {
        return new ServerComputer();
    }

    @Override
    public Mouse getMouse() {
        return new GameMouse();
    }
}
複製程式碼

簡單工廠

概要

  1. 一個抽象產品類
  2. 具體產品類
  3. 一個工廠

優點

  1. 簡單易於實現
  2. 把類的例項化交給工廠,易於解耦

缺點

1.新增具體產品需要修改工廠 違反OCP開放封閉原則

程式碼角度進一步解讀

抽象產品類

/**
 * @author cuishifeng
 * @create 2018-07-09
 **/
public interface Car {

    /**
     * 我有一輛什麼車
     */
     void myCar();
}

複製程式碼

具體產品

/**
 * @author cuishifeng
 * @create 2018-07-09
 **/

public class BenChiCar implements Car {


    @Override
    public void myCar() {
        System.out.println("我有一輛賓士車!");
    }
}
複製程式碼
public class FerrariCar implements Car {

    @Override
    public void myCar() {
        System.out.println("我有一輛法拉利!");
    }
}
複製程式碼
public class LamborghiniCar implements Car {
    @Override
    public void myCar() {
        System.out.println("我有一輛蘭博基尼!");
    }
}
複製程式碼

工廠類

public class CarFactory {

    public static Car createCar(String carName){
        if (carName == null){
            return null;
        }
        switch (carName){
            case "BenChiCar":
                return new BenChiCar();
            case "FerrariCar":
                return new FerrariCar();
            case "LamborghiniCar":
                return new LamborghiniCar();
            default:
                return null;
        }
    }
}
複製程式碼
Car car = CarFactory.createCar("BenChiCar");
car.myCar();

Car car2 = CarFactory.createCar("FerrariCar");
car2.myCar();

輸出

我有一輛賓士車!
我有一輛法拉利!
複製程式碼

總結

簡單工廠模式最大的有點就是工廠內有具體的邏輯去判斷生成什麼產品,將類的例項化交給了工廠,這樣當我們需要什麼產品只需要修改客戶端的呼叫而不需要去修改工廠,對於客戶端來說降低了與具體產品的依賴

工廠方法模式是簡單工廠的擴充套件,工廠方法模式把原先簡單工廠中的實現那個類的邏輯判斷交給了客戶端,如果像新增功能只需要修改客戶和新增具體的功能,不用去修改之前的類。

抽象工廠模式進一步擴充套件了工廠方法模式,它把原先的工廠方法模式中只能有一個抽象產品不能新增產品族的缺點克服了,抽象工廠模式不僅僅遵循了OCP原則(對擴充套件開放,對修改關閉),而且可以新增更多產品(抽象產品),具體工廠也不僅僅可以生成單一產品,而是生成一組產品,抽象工廠也是宣告一組產品,對應擴充套件更加靈活,但是要是擴充套件族系就會很笨重。

相關文章