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 工廠方法
- 定義 : 定義一個創建對象的接口,讓實現這個接口的類來決定實例化哪個類,工廠方法讓類的實例化推遲到子類中進行
- 類型 : 創建型
適用場景
- 創建對象需要大量重複的代碼
- 客戶端(應用層)不依賴於產品類實例如何被創建、實現等細節
- 一個類通過其子類來指定創建哪個對象
- 優點 : 用戶只需要關心所需產品對應的工廠,無須關心創建細節;加入新產品符合開閉原則,提高可擴展性
- 缺點 : 類的個數容易過多,增加複雜度;增加了系統的抽象性和理解難度
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 {