設計模式-創建型-工廠模式
工廠模式
Spring中使用到的工廠模式就是BeanFactory
1、簡單工廠模式
簡單工廠模式(Simple Factory Pattern)是指由一個工廠對象決定創建哪一種產品類的實例
簡單工廠模式適用于工廠類負責創建的對象較少的場景,且客戶端只需要傳入工廠類的參數,對于如何創建對象不需要關心。
1.1、簡單工廠案例
定義一個Icourse接口:
/**
* ICourse接口
* @author ss_419
*/
public interface ICourse {
/** 錄制視頻 **/
public void record();
}
創建一個 Java 課程的實現 JavaCourse 類:
/**
* TODO
*
* @author ss_419
* @version 1.0
* @date 2023/8/31 15:56
*/
public class JavaCourse implements ICourse{
@Override
public void record() {
System.out.println("錄制Java課程。。。。。。");
}
}
客戶端測試代碼如下:
/**
* 原始的調用方法
*/
@Test
public void demo1(){
// 通過向上轉型調用代碼
ICourse course = new JavaCourse();
course.record();
}
在上面的代碼中,父類 ICourse 指向子類 JavaCourse 的引用,應用層代碼需要依賴 JavaCourse,如果業務擴展,繼續增加 PythonCourse 甚至更多課程,那么客戶端的依賴會變得越來越臃腫。
增加課程類 PythonCourse:
/**
* TODO
*
* @author ss_419
* @version 1.0
* @date 2023/8/31 16:00
*/
public class PythonCourse implements ICourse{
@Override
public void record() {
System.out.println("錄制Python課程。。。。。。");
}
}
創建簡單工廠類 CourseFactory:
/**
* TODO 簡單工廠-根據名稱創建實例
*
* @author ss_419
* @version 1.0
* @date 2023/8/31 16:01
*/
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;
}
}
}
修改客戶端調用方式:
/**
* 加入工廠類之后的調用方法
*/
@Test
public void demo2(){
CourseFactory factory = new CourseFactory();
ICourse java = factory.create("java");
java.record();
System.out.println("================================================");
ICourse python = factory.create("python");
python.record();
}
對簡單工廠類進行優化,使用反射機制:
/**
* TODO 通過反射實現的工廠
*
* @author ss_419
* @version 1.0
* @date 2023/8/31 16:05
*/
public class ReflectionCourseFactory {
public ICourse create(String className){
try{
if (!(null == className || "".equals(className))){
// 根據類名反射創建對象
return (ICourse) Class.forName(className).newInstance();
}
}catch (Exception e){
e.printStackTrace();
}
// 沒有傳入類的名字,或者反射沒有找到這個類
return null;
}
}
反射實現簡單工廠,客戶端調用方式:
/**
* 反射工廠測試
*/
@Test
public void demo3(){
ReflectionCourseFactory reflectionCourseFactory = new ReflectionCourseFactory();
ICourse javaCourse =
// 工廠創建參數傳入全限定類名
reflectionCourseFactory.create("org.pp.my.design_pattern.create.factory1.simple_factory.JavaCourse");
javaCourse.record();
}
這里優化之后,方法參數是字符串,還需要強制轉型:
/**
* 不需要進行轉型的反射工廠
* @return
*/
public ICourse createClazz(Class<? extends ICourse> clazz){
try{
if (null != clazz){
return clazz.newInstance();
}
}catch (Exception e){
e.printStackTrace();
}
return null;
}
優化客戶端代碼:
/**
* 不需要轉型的工廠測試
*/
@Test
public void demo4(){
ReflectionCourseFactory reflectionCourseFactory = new ReflectionCourseFactory();
// 這樣就只需要直接傳入ICourse實現類的類類型,就可以構建這個類的對象
ICourse java = reflectionCourseFactory.createClazz(JavaCourse.class);
java.record();
}
2、工廠方法模式
工廠方法模式(Factory Method Pattern)是指定一個創建對象的接口,但讓實現這個接口的類來決定實例化那個類,工廠方法模式讓類的實例化推遲到子類中進行。
在工廠方法模式中用戶只需要關心所需產品對應的工廠,無須關心創建細節,而且加入新產品時符合開閉原則。
2.1、工廠方法案例
創建課程接口:
/**
* ICourse接口
* @author ss_419
*/
public interface ICourse {
/**
* 錄制視頻
*/
public void record();
}
創建 ICourseFactory 接口:
/**
* 對工廠本身進行抽象
*/
public interface ICourseFactory {
/**
* 工廠方法-創建課程
* @return
*/
ICourse create();
}
再分別創建子工廠,JavaCourseFactory:
/**
* TODO 工廠方法-創建子工廠
*
* @author ss_419
* @version 1.0
* @date 2023/8/31 16:21
*/
public class JavaCourseFactory implements ICourseFactory{
@Override
public ICourse create() {
return new JavaCourse();
}
}
PythonCourseFactory:
/**
* TODO
*
* @author ss_419
* @version 1.0
* @date 2023/8/31 16:22
*/
public class PythonCourseFactory implements ICourseFactory{
@Override
public ICourse create() {
return new PythonCourse();
}
}
客戶端測試代碼:
public class FactoryMethodTest {
@Test
public void test1(){
// 創建一個工廠抽象類 --> python
ICourseFactory factory = new PythonCourseFactory();
ICourse course = factory.create();
course.record();
// 更換工廠 --> java
factory = new JavaCourseFactory();
course = factory.create();
course.record();
}
}
工廠方法模式適用于以下場景:
-
創建對象需要大量重復的代碼
-
客戶端(應用層)不依賴于產品實例如何被創建、如何被實現的細節
-
一個類通過子類來指定創建哪個對象
3、抽象工廠模式
抽象工廠模式(Abstract Factory Pattern)是指提供一個創建一系列相關或一系列相互依賴對象的接口,無須指定它們的具體類。
客戶端(應用層)不依賴于產品實例如何被創建、如何被實現等細節,強調的是一系列相關的產品對象(屬于同一產品族)一起使用創建對象需要大量重復的代碼
對接口進行兩次抽象
3.1、抽象工廠案例
創建接口:
/**
* 視頻接口
* @author ss_419
*/
public interface IVideo {
public void record();
}
/**
* 課堂筆記接口
* @author ss_419
*/
public interface INote {
public void edit();
}
創建 一個抽象工廠類 CourseFactory:
/**
* 抽象工廠類
* 抽象工廠類是用戶的主入口
* 是Spring中應用得最廣泛的一種設計模式,易于擴展
* @author ss_419
*/
public interface CourseFactory {
INote createNote();
IVideo createVideo();
}
創建 Java 產品族的 Java 視頻類 JavaVideo:
public class JavaVideo implements IVideo{
@Override
public void record() {
System.out.println("錄制Java視頻");
}
}
擴展產品等級 Java 課堂筆記類 JavaNote:
public class JavaNote implements INote{
@Override
public void edit() {
System.out.println("編寫Java筆記");
}
}
創建 Java 產品族的具體工廠,JavaCourseFactory:
/**
* TODO 創建Java產品族的具體工廠
*
* @author ss_419
* @version 1.0
* @date 2023/8/31 16:38
*/
public class JavaCourseFactory implements CourseFactory{
@Override
public INote createNote() {
return new JavaNote();
}
@Override
創建 Python 產品的 Python 視頻類 PythonVideo:
public class PythonVideo implements IVideo{
@Override
public void record() {
System.out.println("錄制python視頻");
}
}
創建 Python 產品的 Python 筆記類 PythonNote:
public class PythonNote implements INote{
@Override
public void edit() {
System.out.println("編寫Python筆記");
}
}
創建 Python 產品族的具體工廠 PythonCourseFactory:
public class PythonCourseFactory implements CourseFactory{
@Override
public INote createNote() {
return new PythonNote();
}
@Override
public IVideo createVideo() {
return new PythonVideo();
}
}
客戶端調用代碼:
public class AbsFactoryTest {
@Test
public void test1(){
CourseFactory courseFactory = new JavaCourseFactory();
INote javaNote = courseFactory.createNote();
javaNote.edit();
IVideo javaVideo = courseFactory.createVideo();
javaVideo.record();
System.out.println("=====更換工廠======");
// 更換工廠
courseFactory = new PythonCourseFactory();
INote note = courseFactory.createNote();
note.edit();
IVideo video = courseFactory.createVideo();
video.record();
}
}
文章參考:Spring 5 核心原理與 30 個類手寫實戰「Tom 著」
posted on 2023-08-31 23:39 JavaCoderPan 閱讀(27) 評論(0) 收藏 舉報
浙公網安備 33010602011771號