工廠方法模式(FACTORY METHOD)是一種常用的類創建型設計模式,此模式的核心精神是封裝類中變化的部分,提取其中個性化善變的部分爲獨立類,
通過依賴注入以達到解耦、複用和方便後期維護拓展的目的。它的核心結構有四個角色,分別是抽象工廠;具體工廠;抽象產品;具體產品–摘自《百度百科》
前言
寫文章的目的主要是爲了自己知識的鞏固,當然也十分希望在此能夠得到業界前輩們的指導。
本篇文章圍繞:簡單工廠模式、工廠方法模式、抽象工廠模式來大致說明。
設計模式的使用是爲了提高代碼質量、優雅度以及後期更好的重構項目,如果只是爲了實現功能而去編寫代碼就完全沒有這個必要了。當然它的缺點會降低一部分可讀性。
場景:某汽車工廠->根據不同訂單->生產不同品牌的汽車
1.簡單工廠模式(Simple Factory Pattern)
定義:由決定創建出哪一種產品類的實例。
使用場景:簡單工廠模式適用於工廠類對象較少的場景,根據提供的工廠參數來生成不同的產品。無需關心生成過程(new 一個對象的必要條件)
準備工作
//定義一個規範
public interface ICar {
//生產汽車
public void create();
}
//創建一個Audi實現ICar
public class Audi implements ICar {
@Override
public void create() {System.out.println("製造Audi");}
}
//創建一個BMW實現ICar
public class BMW implements ICar {
@Override
public void create() {System.out.println("製造BMW");}
}
以上代碼我們在平時開發中也會經常用到,把公共方法單獨抽象出一個類,如果按照我們以往的方法就是
public static void main(String[] args) {
//需要一個Audi
ICar icar = new Audi();
icar.create();
//在需要一個BMW
ICar icar1 = new BMW();
icar1.create();
//這樣我們每需要一種汽車,我們都需要去單獨創建一個對象.如果品種越來越多,
//代碼就會變的十分臃腫
}
下面我們使用工廠模式對代碼進行優化
1.1 通過類名創建對象
public class CarFactory {
//通過類名創建對象
public ICar create(String name){
if("Audi".equals(name)){
return new Audi();
}else if("BMW".equals(name)){
return new BMW();
}else{//在實際中不建議使用null作爲返回值,會造成空指針不必要的麻煩.
return null;
}
}
}
public static void main(String[] args) {
//調用
CarFactory factory = new CarFactory();//創建一個工廠對象
//需要一個Audi
ICar audi = factory.create("Audi");
//需要一個BMW
ICar bmw = factory.create("BMW");
//此類方法根據傳入的類名來創建實例,對書寫要求較高不允許出現錯誤。顯然不合適
}
1.2通過包名創建對象
public class CarFactory {
//通過類名創建對象
public ICar create(String name){
try {
if(!(null == className ||"".equals(className))){
//通過反射得到類的實例
return (ICar)Class.forName(className).newInstance();
}
}catch (Exception e){
}
return null;
}
}
public static void main(String[] args) {
CarFactory factory = new CarFactory();//創建一個工廠對象
ICar bmw = factory.create("com.xx.BMW")
//此方法通過反射來進行創建,雖然能在一定程度在降低錯誤,因爲我們複製全包名
//的時候往往不會手動輸入(- -! 強行解釋一波),顯然不能解決我們的問題 繼續
}
1.3 通過類對象創建實例
public class CarFactory {
//通過類名創建對象
public ICar create(Class cls){
try {
if(cls != null){
//通過反射得到類的實例
return cls.newInstance();
}
}catch (Exception e){
}
return null;
}
}
public static void main(String[] args) {
CarFactory factory = new CarFactory();//創建一個工廠對象
ICar bmw = factory.create(BMW.class)
//你是不是也覺得這樣錯誤率也就大大降低了。
//相較於原始方法是不是在質量上有那麼一丟丟提高
}
簡單工廠模式
優點:只需傳入一個正確合理的參數,就可以獲取你所需要的對象 無須知道其創建的過程。
缺點:都由工廠統一創建,工廠類的壓力較重,增加新的產品時需要修改工廠類的判斷 邏輯,違背開閉原則,不易於擴展相對複雜的結構。
2.工廠方法模式(Factory Method Pattern)
定義:定義一個接口,讓實現此接口的類來選擇創建哪個類。該工廠不做生產操作,把操作轉交給子工廠相當於代理工廠(打個比方:比如富士康幫助蘋果生產手機,而蘋果本身不生產手機。- - ! 這個比方請不要擡槓)
public interface CarFactory {
//總工廠,將創建邏輯分給代理工廠一對一創建
ICar create();
}
//代理工廠1:生產BMW
public class BMWFactory implements CarFactory{
@Override
public ICar create() {
return new BMW();
}
}
//代理工廠2:生產Audi
public class AudiFactory implements CarFactory{
@Override
public ICar create() {
return new Audi();
}
}
public static void main(String[] args) {
//去Audi工廠要Audi
CarFactory factory = new AudiFactory();
ICar audi = factory.create();
//去BMW工廠要BMW
factory = new BMWFactory();
ICar bmw = factory.create();
}
對工廠方法可以做一些改進:
將CarFactory定義一個抽象類,好處是能添加一些公共的創建條件.
//對工廠方法改進 定義爲一個抽象類
public abstract class CarFactory {
//每個方法創建前的邏輯
public void preCreate(){
}
//公共的方法定義成抽象方法
abstract ICourse create();
}
工廠方法模式:
優點:適用於創建對象時需要大量重複的代碼
缺點:類的個數較多,複雜度增加,相比第一種抽象了些增加了理解難度。
三、抽象工廠模式(Abastract Factory Pattern)
定義:提供一個創建一系列相關或相互依賴對象的接口,無須指定他們具體的類。
什麼意思呢?這裏解釋一下,比方:
1.某一總工廠不單單生產汽車,可能還會生產手機,洗衣機,冰箱等一系列產品。
2.A代理工廠會生產汽車、手機、冰箱、洗衣機。(A生產的產品屬於一系列產品 A品牌)
3.B代理工廠會生產汽車、手機、洗衣機。(B生產的產品屬於一系列產品 B品牌)
下面請看例子:
//所有的工廠都實現這個工廠,一個品牌的抽象
public interface IFactory {
//製造汽車
ICar Car();
//製造電腦
IComputer computer();
}
//A工廠實現
public class AFactory implements IFactory{
@Override
public ICar Car() {
return new Audi();
}
@Override
public IComputer computer() {
return new DellComputer();
}
}
//B工廠實現
public class BFactory implements IFactory{
@Override
public ICar Car() {
return new Audi();
}
@Override
public IComputer computer() {
return new DellComputer();
}
}
public static void main(String[] args) {
//A工廠 生產A品牌的一系列
IFactory factory = new AFactory();
factory.Car();
factory.computer();
//B工廠 生產B品牌的一系列
IFactory factory1 = new BFactory();
factory1.computer();
factory1.Car();
}
抽象類工廠模式:
優點:擴展性非常強、具體產品在應用層代碼隔離,無須關心創建細節、將一個系列的產品統一到一起創建。在spring框架中應該非常廣泛
缺點:不符合開閉原則、如果此工廠增加了一個產品,那麼所有的子工廠都要實現此方法。
試想一下如果IFactory增加了一個產品,A和B以及更多的子工廠都要實現此類方法。
對本文中的補充:
定義:是指一個軟件實體如類、模塊和函數應該對擴展開放,對修改關閉。所謂的開閉,也正是對擴展和修改兩個行爲的一個原則。強調的是用抽象構建框架,用實現擴展細節。可以提高軟件系統的可複用性及可維護性。開閉原則,是面向對象設計中最基礎的設計原則。它指導我們如何建立穩定靈活的系統,例如:我們版本更新,我儘可能不修改源代碼,但是可以增加新功能。請看案例
public class Car {
private String name;
private Double price;
private String color;
public Car(String name, Double price, String color) {
this.name = name;
this.price = price;
this.color = color;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
定義一個汽車,某一天商場做活動,對汽車打折扣如果我們直接修改getPrice()或setPrice()方法會存在一定的風險,可能會影響到其他地方的調用結果。那麼該如何處理?
----另外編寫一個類處理此邏輯
public class CarPrice extends Car{
public CarPrice(String name, Double price, String color) {
super(name, price, color);
}
public Double OriginPrice(){
return super.getPrice();
}
public Double getPrice(){
return super.getPrice()*0.5;
}
}
以上三種方式都有適合自己的場景,沒有好壞之分,具體根據實際情況選擇。
希望各位看過的夥伴們如果發現了問題能夠及時批評指正,在此感謝。