Spring中常見的設計模式——工廠模式
一、簡單工廠模式
簡單工廠模式(Simple Factory Pattern)由一個工廠物件決定建立哪一種產品類的例項,簡單工廠模式適用於工廠類負責建立物件較少的情況,且客戶端只需要傳入工廠類的引數,對於如何建立物件不關心。
public interface IBlog { //寫隨筆 public void write(); }
public class JavaBlog implements IBlog { @Override public void write() { System.out.println("寫java隨筆"); } }
public class WriteBlog { public static void main(String[] args) { IBlog blog = new JavaBlog(); blog.write(); } }
上述程式碼中,父類 IBlog 指向子類JavaBlog 的引用,應用層需要依賴JavaBlog,如果增加PythonBlog等等更多的課程,客戶端就會越來越臃腫。因此要把依賴減弱,把建立細節隱藏。現在我們用簡單工廠優化:
public class BlogFactory { public IBlog create(Class<? extends IBlog> clazz) { if (null != clazz) { try { return clazz.newInstance(); } catch (Exception e) { e.printStackTrace(); } } return null; } }
客戶端改變:
public static void main(String[] args) { BlogFactory blogFactory = new BlogFactory(); IBlog blog = blogFactory.create(JavaBlog.class); blog.write(); }
簡單工廠模式在JDK中很常見,如Calender類(感興趣去看原始碼),還有logback,LoggerFactory中有很多過載的方法getLogger()。但是簡單工廠也有缺點:工廠類的職責相對過重,不易於擴充套件過於複雜的產品結構。
二、工廠方法模式
工廠方法模式(Factory Method Pattern)是指定義一個建立物件的介面,但讓實現這個介面的類來決定例項化哪個類,工廠方法模式讓類的例項化推遲到子類中進行。在工廠方法模式中,使用者只需要關心所需產品對應工廠,無須關心建立的細節,而且加入新產品時符合開閉原則。
工廠方法模式主要解決產品擴充套件問題。在簡單工廠模式中,隨著產品的增多,如果不同語言書寫隨筆的邏輯各不相同,工廠職責越來越多,那工廠裡面就會亂搞一氣,狗屁不通。根據單一職責原則,我們將只能進行拆分,不同工廠做不同事,Java隨筆由Java工廠建立,Python隨筆由Python工廠建立,對工廠本身進行抽象。
先建立工廠類:
public interface IBlogFactory { IBlog create(); }
再建立對應工廠:
public class JavaBlogFactory implements IBlogFactory { @Override public IBlog create() { return new JavaBlog(); } } public class PythonBlogFactory implements IBlogFactory { @Override public IBlog create() { return new PythonBlog(); } }
客戶端:
public class CreateBlog { public static void main(String[] args) { IBlogFactory factory = new PythonBlogFactory(); IBlog blog = factory.create(); blog.write(); factory = new JavaBlogFactory(); blog = factory.create(); blog.write(); } }
總結來說就是:不同工廠抽象出一個工廠頭子,不同的工廠建立不同的例項。
工廠方法模式適用於以下場景:
1.建立物件需要大量重複程式碼。
2.客戶端(應用層)不依賴於產品類例項如何被建立、如何被實現等細節。
3.一個類通過其子類來指定建立哪個物件。
缺點:
1.類的個數容易過多,增加複雜度。
2.增加了系統的抽象性和理解難度。
三、抽象工廠
抽象工廠(Abstract Factory Pattern)提供一個黃健一系列相關或相互依賴物件的介面,無需指定具體類。客戶端(應用層)不依賴於產品類例項如何被建立、如何被實現等細節,強調的是一系列相關得產品物件(屬於同一產品族)一起使用建立物件需要大量重複程式碼。需要提供一個產品類的庫,所有產品以同樣接口出現,從而是客戶端不依賴於具體實現。
產品族:同一家的不同產品,比如小米,華為,蘋果;
產品等級:不同種類的產品,比如 手機,電視,電腦。
工廠要做的就是生產我們牌子的所有產品。以部落格為例,java分類的部落格有隨筆、文章、日記等。
首先建立文章和日記的抽象介面:
public interface IDocument { void write(); } public interface INote { void make(); }
再建立抽象工廠:
public interface BlogFactory { INote createNote(); IDocument createDocument(); }
實現Java文章和日記:
public class JavaDocument implements IDocument { @Override public void write() { System.out.println("寫Java文章"); } } public class JavaNote implements INote { @Override public void make() { System.out.println("寫Java筆記"); } }
實現Java產品族具體工廠:
public class JavaBlogFactory implements BlogFactory { @Override public INote createNote() { return new JavaNote(); } @Override public IDocument createDocument() { return new JavaDocument(); } }
實現Python文章和日記、實現Python具體工廠參考Java的。
客戶端呼叫:
public class BlogTest { public static void main(String[] args) { JavaBlogFactory factory = new JavaBlogFactory(); factory.createDocument().write(); factory.createNote().make(); } }
上述程式碼描述了兩個產品族的工廠,如果想要擴充套件產品等級(就是再加點評啥的),要調整抽象工廠、具體工廠。由此可見抽象工廠模式的缺點:
1.規定所有可能被建立的產品集合,產品族(Java系列)中擴充套件新產品很困難,需要修改抽象工廠及實現;
2.增加系統抽象性和理解難度;
我們可以利用工廠模式建立好資料來源連線池並放到容器中,業務需要時再取出。就避免了用一次建立一次的尷尬。
&n