創建型模式【2】——工廠設計模式


1 不用工廠實現業務 

public abstract class Video {
    //生產視頻
    public abstract void produce();
}
public class JavaVideo extends Video {
    @Override
    public void produce() {
        System.out.println("錄製Java課程視頻");
    }
}
public class PythonVideo extends Video {
    @Override
    public void produce() {
        System.out.println("錄製Python課程視頻");
    }
}


2 簡單工廠

2.1 簡單工廠分析

  • 定義 : 由一個工廠對象決定創建出哪一種產品類的實例
  • 類型 : 創建型,但不屬於GOF23種設計模式

適用場景

  • 工廠類負責創建的對象比較少
  • 客戶端(應用層)只知道傳入工廠類的參數,對於如何創建對象(邏輯)不關心
  • 優點 : 只需要傳入一個正確的參數,就可以獲取你所需要的對象,而無須知道其創建細節
  • 缺點 : 工廠類的職責相對過重,增加新的產品,需要修改工廠類的判斷邏輯,違背開閉原則

2.2 Coding

public abstract class Video {
    //生產視頻
    public abstract void produce();
}
public class JavaVideo extends Video {
    @Override
    public void produce() {
        System.out.println("錄製Java課程視頻");
    }
}
public class PythonVideo extends Video {
    @Override
    public void produce() {
        System.out.println("錄製Python課程視頻");
    }
}
public class VideoFactory {
    //可以用static修飾,調用更簡單
    public Video getVideo(String type) {
        if ("java".equalsIgnoreCase(type)) {
            return new JavaVideo();
        } else if ("python".equalsIgnoreCase(type)) {
            return new PythonVideo();
        }
        //如需增加,還需要修改代碼才能實現,不符合開閉原則
        return null;
    }
}

2.3 升級簡單工廠 

public class VideoFactory {
    public Video getVideo(Class c) {
        Video video = null;
        try {
            // 後面需要增加產品這裏無需改動
            video = (Video) Class.forName(c.getName()).newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return video;
    }
}
public class VideoTest {
    @Test
    public void test() {
        VideoFactory videoFactory = new VideoFactory();
        Video video = videoFactory.getVideo(JavaVideo.class);
        if (video == null) {
            return;
        }
        video.produce(); // 錄製Java課程視頻
    }
}

3 工廠方法

  • 定義 : 定義一個創建對象的接口,讓實現這個接口的類來決定實例化哪個類,工廠方法讓類的實例化推遲到子類中進行
  • 類型 : 創建型

適用場景

  1. 創建對象需要大量重複的代碼
  2. 客戶端(應用層)不依賴於產品類實例如何被創建、實現等細節
  3. 一個類通過其子類來指定創建哪個對象
  • 優點 : 用戶只需要關心所需產品對應的工廠,無須關心創建細節;加入新產品符合開閉原則,提高可擴展性
  • 缺點 : 類的個數容易過多,增加複雜度;增加了系統的抽象性和理解難度
public abstract class Video {
    //生產視頻
    public abstract void produce();
}
public class JavaVideo extends Video {
    @Override
    public void produce() {
        System.out.println("錄製Java課程視頻");
    }
}
public class PythonVideo extends Video {
    @Override
    public void produce() {
        System.out.println("錄製Python課程視頻");
    }
}
public abstract class VideoFactory {
    public abstract Video getVideo();
}
public class JavaVideoFactory extends VideoFactory {
    @Override
    public Video getVideo() {
        return new JavaVideo();
    }
}
public class PythonVideoFactory extends VideoFactory {
    @Override
    public Video getVideo() {
        return new PythonVideo();
    }
}

源碼分析 

//java.util.Collection
public interface Collection<E> extends Iterable<E> {
    //具體實現交給子類
    Iterator<E> iterator();
//java.util.ArrayList
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable
    public Iterator<E> iterator() {
        return new Itr();
    }
    private class Itr implements Iterator<E> {
//<dependency>
//    <groupId>org.slf4j</groupId>
//    <artifactId>slf4j-api</artifactId>
//    <version>1.7.30</version>
//</dependency>
//<dependency>
//    <groupId>ch.qos.logback</groupId>
//    <artifactId>logback-classic</artifactId>
//    <version>1.2.3</version>
//</dependency>

//org.slf4j.LoggerFactory#getLogger(java.lang.String)
public static Logger getLogger(String name) {
	ILoggerFactory iLoggerFactory = getILoggerFactory();
	return iLoggerFactory.getLogger(name);
}
public interface ILoggerFactory {
    //工廠方法
    public Logger getLogger(String name);
}

//ch.qos.logback.classic.LoggerContext#getLogger(java.lang.String)
public final Logger getLogger(String name) {
//org.slf4j.helpers.NOPLoggerFactory#getLogger
public Logger getLogger(String name) {
//org.slf4j.helpers.SubstituteLoggerFactory#getLogger
synchronized public  Logger getLogger(String name) {

4 抽象工廠

  • 定義 : 抽象工廠模式提供一個創建一系列相關或相互依賴對象的接口,無須指定它們具體的類
  • 類型 : 創建型

適用場景

  • 客戶端(應用層)不依賴於產品類實例如何被創建、實現等細節
  • 強調一系列相關的產品對象(屬於同一產品族)一起使用創建對象需要大量重複的代碼
  • 提供一個產品類的庫,所有的產品以同樣的接口出現,從而使客戶端不依賴於具體實現
  • 優點 : 具體產品在應用層代碼隔離,無須關心創建細節;將一個系列的產品族統一到一起創建
  • 缺點 : 規定了所有可能被創建的產品集合,產品族中擴展新的產品困難,需要修改抽象工廠的接口;增加了系統的抽象性和理解難度

public abstract class Article {
    public abstract void produce();
}
public class JavaArticle extends Article {
    @Override
    public void produce() {
        System.out.println("編寫Java課程手記");
    }
}
public class PythonArticle extends Article {
    @Override
    public void produce() {
        System.out.println("編寫Python課程手記");
    }
}
public abstract class Video {
    public abstract void produce();
}
public class JavaVideo extends Video {
    @Override
    public void produce() {
        System.out.println("錄製Java課程視頻");
    }
}
public class PythonVideo extends Video {
    @Override
    public void produce() {
        System.out.println("錄製Python課程視頻");
    }
}
public interface CourseFactory {
    Video getVideo();
    Article getArticle();
}
public class JavaCourseFactory implements CourseFactory {
    @Override
    public Video getVideo() {
        return new JavaVideo();
    }
    @Override
    public Article getArticle() {
        return new JavaArticle();
    }
}
public class PythonCourseFactory implements CourseFactory {
    @Override
    public Video getVideo() {
        return new PythonVideo();
    }
    @Override
    public Article getArticle() {
        return new PythonArticle();
    }
}
public class VideoAndArticleTest {
    // 新增產品族容易(滿足開閉原則)
    // 新增產品等級麻煩,需要修改原有的代碼(違背了開閉原則),比如除了視頻手記之外還需要增加源代碼纔是一個完整的課程,這個時候對原有的修改就比較大了
    // 適合於產品等級固定,產品族多變的環境
   @Test
   public void test(){
       CourseFactory courseFactory = new JavaCourseFactory();
       // 取出的一定是JAVA產品族,減少產生錯誤的可能
       Video video = courseFactory.getVideo();
       Article article = courseFactory.getArticle();
       video.produce(); // 錄製Java課程視頻
       article.produce(); // 編寫Java課程手記
   }
}

源碼分析 

//java.sql.Connection
public interface Connection  extends Wrapper, AutoCloseable {

//<dependency>
//    <groupId>mysql</groupId>
//    <artifactId>mysql-connector-java</artifactId>
//    <version>8.0.20</version>
//</dependency>
//com.mysql.cj.jdbc.ConnectionImpl
public class ConnectionImpl implements JdbcConnection, SessionEventListener, Serializable {
//java.sql.Statement
public interface Statement extends Wrapper, AutoCloseable {
//<dependency>
//    <groupId>org.mybatis</groupId>
//    <artifactId>mybatis</artifactId>
//    <version>3.5.4</version>
//</dependency>

//org.apache.ibatis.session.SqlSessionFactory
public interface SqlSessionFactory {

 

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