抽象模式這麼抽象啊?

抽象工廠模式

今天我們來學習一下第三種設計模式——抽象工廠模式,

概念:

所謂抽象工廠模式就是提供一個接口,用於創建相關或者依賴對象的家族,而不需要明確指定具體類。它允許客戶端使用抽象的接口來創建一組相關的產品,而不需要關心實際產出的具體產品是什麼。這樣一來,客戶就可以從具體的產品中被解耦。它的優點是隔離了具體類的生成,使得客戶端不需要知道什麼被創建了,而缺點就在於新增新的行爲會比較麻煩,因爲當添加一個新的產品對象時,需要更改接口及其下的所有子類。

特點:
  • 可以在類的內部對產品族中相關聯的多等級產品共同管理,而不必專門引入多個新的類來進行管理。
  • 當增加一個新的產品族時不需要修改原代碼,滿足開閉原則。
  • 其缺點是:當產品族中需要增加一個新的產品時,所有的工廠類都需要進行修改。
抽象工廠模式的主要角色 :
  • 抽象工廠(Abstract Factory):提供了創建產品的接口,它包含多個創建產品的方法 new Product(),可以創建多個不同等級的產品。
  • 具體工廠(Concrete Factory):主要是實現抽象工廠中的多個抽象方法,完成具體產品的創建。
  • 抽象產品(Product):定義了產品的規範,描述了產品的主要功能和特性,抽象工廠模式有多個抽象產品。
  • 具體產品(Concrete Product):實現了抽象產品角色所定義的接口,由具體工廠來創建,它同具體工廠之間是多對一的關係。
類圖分析:

代碼:

抽象工廠模式的抽象層

package cn.ppdxzz.abstractfactory;

/**
 * Description:抽象工廠模式的頂級抽象層
 * @Author: PeiChen
 */
public interface AbstractFactory {
    //定義一個創建圖形的方法,讓其子類具體實現
    Graph createGraph(String createType);
}

小萬繪圖的工廠子類

package cn.ppdxzz.abstractfactory;

/**
 * Description:小萬繪圖的工廠子類
 * @Author: PeiChen
 */
public class WanFactory implements AbstractFactory{

    @Override
    public Graph createGraph(String createType) {
        Graph graph = null;
        if ("circle".equals(createType)) {
            graph = new WanCircle();
        }else if ("rectangle".equals(createType)) {
            graph = new WanRectangle();
        }
        return graph;
    }
}

小李繪圖的工廠子類

package cn.ppdxzz.abstractfactory;

/**
 * Description:小李繪圖的工廠子類
 * @Author: PeiChen
 */
public class LiFactory implements AbstractFactory {
    @Override
    public Graph createGraph(String createType) {
        Graph graph = null;
        if ("circle".equals(createType)) {
            graph = new LiCircle();
        }else if ("rectangle".equals(createType)) {
            graph = new LiRectangle();
        }
        return graph;
    }
}

圖形抽象類

package cn.ppdxzz.abstractfactory;

/**
 * Description:圖形抽象類
 * @Author: PeiChen
 */
public abstract class Graph {
    //開始繪製
    public abstract void startDraw();
    //結束繪製
    public abstract void finishDraw();
}

小萬繪製圓形的具體實現

package cn.ppdxzz.abstractfactory;

/**
 * Description:小萬繪製圓形
 * @Author: PeiChen
 */
public class WanCircle extends Graph {
    @Override
    public void startDraw() {
        System.out.println("小萬開始繪製圓形...");
    }

    @Override
    public void finishDraw() {
        System.out.println("小萬結束繪製圓形...");
        System.out.println("-------------------");
    }
    
}

小李繪製矩形的具體實現

package cn.ppdxzz.abstractfactory;

/**
 * Description:小李繪製矩形
 * @Author: PeiChen
 */
public class LiRectangle extends Graph {
    @Override
    public void startDraw() {
        System.out.println("小李開始繪製矩形...");
    }

    @Override
    public void finishDraw() {
        System.out.println("小李結束繪製矩形...");
        System.out.println("-------------------");
    }
}

繪圖的工具類

package cn.ppdxzz.abstractfactory;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * Description:繪圖的工具類
 * @Author: PeiChen
 */
public class DrawGraph {

    AbstractFactory factory;

    //構造方法
    public DrawGraph(AbstractFactory factory) {
        setFactory(factory);
    }

    private void setFactory(AbstractFactory factory) {
        Graph graph = null;
        String createType = "";
        this.factory = factory;
        do {
            createType = getType();
            //factory可能是小萬的工廠子類,也可能是小李的工廠子類
            graph = factory.createGraph(createType);
            if (graph != null) {
                graph.startDraw();
                graph.finishDraw();
            }else {
                System.out.println("輸入有誤,您已退出!");
                break;
            }

        }while (true);

    }

    //獲取繪製者繪製的圖形形狀
    private String getType() {
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("請輸入需要繪製的圖形形狀:");
            String str = reader.readLine();
            return str;
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }
    }
}

圖形的具體繪製者

package cn.ppdxzz.abstractfactory;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * Description:圖形繪製者
 * @Author: PeiChen
 */
public class DrawPerson {
    public static void main(String[] args) {
        System.out.println("請輸入繪製者的姓名:");
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
            String name = reader.readLine();
            if ("xw".equals(name)) {
                new DrawGraph(new WanFactory());
            }else {
                new DrawGraph(new LiFactory());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

演示:

JDK源碼分析(Calendar類就屬於簡單工廠模式,這個我沒有講解,因爲他不屬於23種設計模式):

總結:
  • 抽象工廠模式的擴展有一定的“開閉原則”傾斜性。

    • 當增加一個新的產品族時只需增加一個新的具體工廠,不需要修改原代碼,滿足開閉原則;

    • 當產品族中需要增加一個新種類的產品時,則所有的工廠類都需要進行修改,不滿足開閉原則。

  • 另一方面,當系統中只存在一個等級結構的產品時,抽象工廠模式將退化到工廠方法模式。

  • 從設計層面看,抽象工廠模式就是對簡單工廠模式的改進(或者稱爲進一步的抽象)。

  • 將工廠抽象成兩層,Abstract Factory(抽象工廠) 和具體實現的工廠子類。程序員可以根據創建對象類型使用對應的工廠子類。這樣將單個的簡單工廠類變成了工廠簇, 更利於代碼的維護和擴展。

抽象工廠模式就講解到這裏吧,下一個設計模式是建造者模式,敬請期待。

微信公衆號:JavaAnything,期待你的關注!
在這裏插入圖片描述
微信交流羣
在這裏插入圖片描述

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