設計模式-簡單工廠,工廠模式和抽象工廠

1. 簡單工廠

1.1 定義

  • 簡單工廠是由一個工廠對象創建出哪一種產品類的實例,是創建型的一種但不屬於GOF23中設計模式之一。

1.2 使用場景

  • 工廠類負責創建的對象較少。
  • 應用層只知道傳入工廠類的參數,對於如何創建對象的邏輯並不關心。

1.3 模擬代碼

  • 以錄製視頻爲例,現在有Java課程的視頻,Python的視頻,通過簡單工廠的方式將課程實例化。

  • 抽象類Video

package com.fukexin.design.pattern.creational.simplefactory;

public abstract class Video {

    public abstract void produce();
}
  • 子類JavaVideo繼承於Video
package com.fukexin.design.pattern.creational.simplefactory;

public class JavaVideo extends Video {
    public void produce() {
        System.out.println("錄製Java課程視頻");
    }
}
  • 子類PythonVideo繼承於Video
package com.fukexin.design.pattern.creational.simplefactory;

public class PythonVideo  extends Video{

    public void produce() {
        System.out.println("錄製Python課程視頻");
    }
}
  • 工廠類VideoFactory用於生產具體的Video(使用反射創建實例的好處是符合開閉原則,即對擴展開放,對修改關閉)
package com.fukexin.design.pattern.creational.simplefactory;

import java.lang.reflect.InvocationTargetException;

public class VideoFactory {

    public Video getInstance(Class c){
        Video video=null;
        try {
            video= (Video) Class.forName(c.getName()).getDeclaredConstructor().newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return video;
    }
}
  • UML類圖
    在這裏插入圖片描述

1.4 應用源碼解析

  • java.util.Calendar中的getIntance()方法調用了createCalendar()方法。會根據傳入的語言和國家來實例化不同的Calendar。
 if (cal == null) {
            if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {
                cal = new BuddhistCalendar(zone, aLocale);
            } else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja" && aLocale.getCountry() == "JP") {
                cal = new JapaneseImperialCalendar(zone, aLocale);
            } else {
                cal = new GregorianCalendar(zone, aLocale);
            }
        }
  • UML類圖
    在這裏插入圖片描述

2. 工廠方法

2.1 定義

  • 定義一個創建對象的接口,但讓實現這個接口的類決定實例化哪個類,工廠方法讓類的實例化推遲到子類中進行。
  • 主要是針對同一產品等級(如海爾的冰箱,西門子的冰箱,美的的冰箱…z)。

2.2 適用場景

  • 創建對象需要大量的重複代碼。
  • 應用層不依賴於產品類實例如何被創建,實現等細節。
  • 一個類通過子類來指定創建哪個對象。

2.3 模擬代碼

  • 以錄製視頻爲例,現在有Java課程的視頻,Python的視頻,通過簡單工廠的方式將課程實例化。
  • 抽象產品類Video
package com.fukexin.design.pattern.creational.factorymethod;

public abstract class Video {

    public abstract void produce();
}
  • 具體產品類JavaVideo
package com.fukexin.design.pattern.creational.factorymethod;

public class JavaVideo extends Video {
    public void produce() {
        System.out.println("錄製Java課程視頻");
    }
}

  • 具體產品類PythonVideo
package com.fukexin.design.pattern.creational.factorymethod;

public class PythonVideo  extends Video {

    public void produce() {
        System.out.println("錄製Python課程視頻");
    }
}
  • 具體產品類FEVideo
package com.fukexin.design.pattern.creational.factorymethod;

public class FEVideo extends Video {
    public void produce() {
        System.out.println("錄製FE課程視頻");
    }
}

  • 抽象工廠類VideoFactory
package com.fukexin.design.pattern.creational.factorymethod;


public abstract class VideoFactory {

    public abstract Video getInstance();
}
  • 生產Java視頻的工廠類JavaVideoFactory
package com.fukexin.design.pattern.creational.factorymethod;

public class JavaVideoFactory extends VideoFactory {
    public Video getInstance() {
        return new JavaVideo();
    }
}

  • 生產Python視頻的工廠類PythonVideoFactory
package com.fukexin.design.pattern.creational.factorymethod;

public class PythonVideoFactory extends  VideoFactory{

    public Video getInstance() {
        return new PythonVideo();
    }
}

  • 生產FE視頻的工廠類FEVideoFactory
package com.fukexin.design.pattern.creational.factorymethod;

public class FEVideoFactory extends VideoFactory {

    public Video getInstance() {
        return new FEVideo();
    }
}

  • UML類圖
    在這裏插入圖片描述

2.4 應用源碼解析

  • java.util.Collection中的Iterator()可以看作爲一個工廠方法,它返回的Iterator即爲抽象產品,其中ArrayList中的Itr類實現Iterator接口,即爲實際產品。
	    public Iterator<E> iterator() {
        return new ArrayList.Itr();
    }
 private class Itr implements Iterator<E> 

3. 抽象工廠

3.1 定義

  • 抽象工廠模式提供了一個創建一系列相關或相互依賴對象的接口。

3.2 適用場景

  • 應用層不依賴於產品類實例如何被創建,實現等細節。
  • 強調一系列相關的產品對象(屬於同一產品族,如美的的冰箱,美的的空調,美的的抽油煙機等)一起使用創建對象需要大量重複的代碼。
  • 提供產品類的庫,所有的產品以同樣的接口出現,從而使客戶端不依賴於具體實現。

3.3 模擬代碼

  • 場景:一個視頻不能稱作一個課程,現在要求課程必須有視頻,有手記。所以在Java這個產品族中使用抽象工廠模式。
  • Video抽象類
package com.fukexin.design.pattern.creational.abstractfactory;

public abstract class Video {
    public abstract void produce();
}
  • JavaVideo具體類
package com.fukexin.design.pattern.creational.abstractfactory;

public class JavaVideo extends Video {
    public void produce() {
        System.out.println("錄製Java課程視頻");
    }
}
  • PythonVideo具體類
package com.fukexin.design.pattern.creational.abstractfactory;

public class PythonVideo extends Video {
    public void produce() {
        System.out.println("錄製Python課程視頻");
    }
}
  • Article抽象類
package com.fukexin.design.pattern.creational.abstractfactory;

public  abstract class Article {
    public abstract void produce();
}
  • JavaArticle具體類
package com.fukexin.design.pattern.creational.abstractfactory;

public class JavaArticle extends Article {
    public void produce() {
        System.out.println("編寫Java課程手記");
    }
}
  • PythonArticle具體類
package com.fukexin.design.pattern.creational.abstractfactory;

public class PythonArticle extends Article {
    public void produce() {
        System.out.println("編寫Python課程手記");
    }
}
  • CourseFactory接口
package com.fukexin.design.pattern.creational.abstractfactory;

public interface CourseFactory {

    public Video getVideo();

    public Article getArticle();
}
  • JavaCourseFactory工廠類
package com.fukexin.design.pattern.creational.abstractfactory;

public class JavaCourseFactory implements CourseFactory {
    public Video getVideo() {
        return new JavaVideo();
    }

    public Article getArticle() {
        return new JavaArticle();
    }
}
  • PythonCourseFactory工廠類
package com.fukexin.design.pattern.creational.abstractfactory;

public class PythonCourseFactory implements CourseFactory {
    public Video getVideo() {
        return new PythonVideo();
    }

    public Article getArticle() {
        return new PythonArticle();
    }
}
  • UML類圖
    在這裏插入圖片描述

3.4 應用源碼解析

  • java.util.Conection接口中對於一個同connection的createStatement()方法返回的Statement,createPrepareStatement()方法返回的PrepareStatement屬於同一產品族。
	Statement createStatement() throws SQLException;

	PreparedStatement prepareStatement(String var1) throws SQLException;
  • MyBatis中的SqlSesstionFactory中的openSession方法和getConfiguration()方法,其中openSession()方法返回的session也是一個接口(即抽象產品)。
    SqlSession openSession(ExecutorType var1, Connection var2);

    Configuration getConfiguration();

4. 比較

  • 工廠方法和抽象工廠是對簡單工廠的延伸和拓展,工廠方法主要關注產品等級(西門子的冰箱,美的的冰箱,海爾的冰箱),而抽象工廠關注的是產品族(美的的空調,美的的冰箱,美的的抽油煙機)。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章