Spring常用設計模式-工廠模式

簡單工廠模式

簡單工廠模式是指由一個工廠對象決定創建哪一種產品類的實例。
以課程爲例,假如目前某學院開設Java架構、大數據、人工智能等課程,通常的寫法:

public interface ICourse {
    /** 錄製視頻 */
    public void record();
}

public class JavaCourse implements ICourse {
    @Override
    public void record() {
        System.out.println("錄製Java視頻");
    }
}

public class PythonCourse implements ICourse {
    @Override
    public void record() {
        System.out.println("錄製Python視頻");
    }
}

public class Test {
    public static void main(String[] args) {
        ICourse javaCourse = new JavaCourse();
        javaCourse.record();
        ICourse pythonCourse = new PythonCourse();
        pythonCourse.record();
    }
}

Test類需要依賴JavaCourse和PythonCourse,如果還有別的課程,那麼Test還將繼續依賴,違背了迪米特原則。
現在用簡單工廠模式進行優化,首先創建一個CourseFactory工廠類。

public class CourseFactory {
    public ICourse create(String name) {
        if("java".equals(name)) {
            return new JavaCourse();
        } else if("python".equals(name)) {
            return new PythonCourse();
        } else {
            return null;
        }
    }
}

public class SimpleFactoryTest {
    public static void main(String[] args) {
        CourseFactory courseFactory = new CourseFactory();
        courseFactory.create("java");
        courseFactory.create("python");
    }
}

客戶端調用時變簡單了,但是工廠類的設計不符合開閉原則,因爲如果要增加前端課程,那麼工廠的create()方法就要修改代碼,繼續優化。

public class CourseFactory {
    public ICourse create(String className) {
        if(!(null == className || "".equals(className))) {
            try {
                return (ICourse) Class.forName(className).newInstance();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}

public class SimpleFactoryTest {
    public static void main(String[] args) {
        CourseFactory courseFactory = new CourseFactory();
        ICourse course = courseFactory.create("cn.itdjn.ch2.ch2_2.ch2_2_2.JavaCourse");
        course.record();
    }
}

現在不需要修改CourseFactory中的代碼,但方法參數是字符串,可控性有待提升,而且還需要強制類型轉換,繼續優化。

public class CourseFactory {
    public ICourse create(Class<? extends ICourse> clazz) {
        try {
            if(null != clazz) {
                return clazz.newInstance();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

public class SimpleFactoryTest {
    public static void main(String[] args) {
        CourseFactory courseFactory = new CourseFactory();
        ICourse course = courseFactory.create(JavaCourse.class);
        course.record();
    }
}

工廠方法模式

定義一個創建對象的接口,讓實現這個接口的類決定實例化哪個類,工廠方法模型讓類的實例化推遲到子類中進行。簡單工廠模式中隨着產品鏈的豐富,可能會出現每個課程創建邏輯上的區別,這個時候單一的簡單工廠模式就會變得不易於維護。我們需要根據單一職責原則將職能區分,專人幹專事。此時Java課程由Java工廠創建,Python課程由Python工廠創建。

public interface ICourseFactory {
    ICourse create();
}

public class JavaCourseFactory implements ICourseFactory {
    @Override
    public ICourse create() {
        return new JavaCourse();
    }
}

public class PythonCourseFactory implements ICourseFactory {
    @Override
    public ICourse create() {
        return new PythonCourse();
    }
}

public class Test {
    public static void main(String[] args) {
        ICourseFactory factory = new PythonCourseFactory();
        ICourse course = factory.create();
        course.record();

        factory = new JavaCourseFactory();
        course = factory.create();
        course.record();
    }
}

抽象工廠模式

在這裏插入圖片描述
先解釋什麼是產品族,上圖第一行假設都是美的公司生產的家用電器,那麼正方形表示美的冰箱,圓形表示美的空調,菱形表示美的熱水器。那麼第二行可能就是格力冰箱、格力空調、格力熱水器,依次類推。
在解釋什麼產品等級結構,上圖第一列都是冰箱,第二列都是空調,第三列都是熱水器,但是每行屬於不同的廠家製造的。那廠家不同,工廠也就不一樣,所以延伸出下面的圖形。
在這裏插入圖片描述
由上圖可以看出,第一行的美的產品是由美的工廠生產的,第二行的格力產品是由格力工廠生產的,這兩個工廠是不同的具體工廠。
以上面的電器爲例,假如現在要製造冰箱、空調、洗衣機,那麼這三個產品是三個不同的產品等級結構。
冰箱、空調、洗衣機接口如下:

/**
 * 空調
 */
public interface IAirConditioner {
    void refrigeration(); // 製冷
}
/**
 * 冰箱
 */
public interface IRefrigerator {
    void coldStorage(); // 冷藏
}
/**
 * 洗衣機
 */
public interface IWashingMachine {
    void washClothes(); // 洗衣服
}

抽象工廠類:

/**
 * 抽象工廠
 */
public interface HomeApplianceFactory {
    IRefrigerator createRefrigerator();
    IAirConditioner createAirConditioner();
    IWashingMachine createWashingMachine();
}

具體不同廠家的冰箱、空調、洗衣機:

/**
 * 美的空調
 */
public class BeautifulAirConditioner implements IAirConditioner {
    @Override
    public void refrigeration() {
        System.out.println("美的空調可以製冷");
    }
}
/**
 * 美的冰箱
 */
public class BeautifulRefrigerator implements IRefrigerator {
    @Override
    public void coldStorage() {
        System.out.println("美的冰箱冷藏食物");
    }
}
/**
 * 美的洗衣機
 */
public class BeautifulWashingMachine implements IWashingMachine {
    @Override
    public void washClothes() {
        System.out.println("美的洗衣機可以洗衣服");
    }
}
/**
 * 格力空調
 */
public class GreeAirConditioner implements IAirConditioner {
    @Override
    public void refrigeration() {
        System.out.println("格力空調可以製冷");
    }
}
/**
 * 格力冰箱
 */
public class GreeRefrigerator implements IRefrigerator {
    @Override
    public void coldStorage() {
        System.out.println("格力冰箱冷藏食物");
    }
}
/**
 * 格力洗衣機
 */
public class GreeWashingMachine implements IWashingMachine {
    @Override
    public void washClothes() {
        System.out.println("格力洗衣機可以洗衣服");
    }
}

具體不同廠家的工廠類:

/**
 * 美的工廠
 */
public class BeautifulFactory implements HomeApplianceFactory {
    @Override
    public IRefrigerator createRefrigerator() {
        return new BeautifulRefrigerator();
    }

    @Override
    public IAirConditioner createAirConditioner() {
        return new BeautifulAirConditioner();
    }

    @Override
    public IWashingMachine createWashingMachine() {
        return new BeautifulWashingMachine();
    }
}
/**
 * 格力工廠
 */
public class GreeFactory implements HomeApplianceFactory{
    @Override
    public IRefrigerator createRefrigerator() {
        return new GreeRefrigerator();
    }

    @Override
    public IAirConditioner createAirConditioner() {
        return new GreeAirConditioner();
    }

    @Override
    public IWashingMachine createWashingMachine() {
        return new GreeWashingMachine();
    }
}

測試類:

public class Test {
    public static void main(String[] args) {
        HomeApplianceFactory factory = new BeautifulFactory();
        factory.createAirConditioner().refrigeration();
        factory.createRefrigerator().coldStorage();
        factory.createWashingMachine().washClothes();
        factory = new GreeFactory();
        factory.createAirConditioner().refrigeration();
        factory.createRefrigerator().coldStorage();
        factory.createWashingMachine().washClothes();
    }
}

上述完整的描述了兩個產品族,但是如果繼續擴展產品等級,比如增加電風扇,那代碼從抽象工廠到具體工廠都要調整,這違背了開閉原則,因此抽象工廠也是有缺點的,但是是可接受的,只要不是過於頻繁的升級。

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