簡單工廠、工廠模式初學習

Ajiajiajia發表於2018-03-28

借鑑 :《大話資料結構》 http://www.cnblogs.com/cj723/

活字印刷--物件導向

活字印刷,即當需要改變部分字的時候,不需要整個刻板全部重新刻,解耦。

  • 可維護
    • 要改,只需更改要改之字
  • 可複用
    • 這些字並非這次用完就無用,完全可以後來的印刷中重複使用
  • 可擴充套件
    • 若需要在已有內容里加字,只需要另刻字加入即可
  • 靈活性好
    • 子的排版可能是豎排也可能是橫排,需求改變時只需要將活字移動就克做到滿足排列需求

所以需要通過 封裝、繼承、多型把程式的耦合度降到最低

  • 業務的封裝
    • 將業務邏輯與介面邏輯分開,讓他們之間的耦合度下降
    • 比如一個Windows計算器,將計算和顯示分開
      • Operation運算類
        • 加減乘除功能具體實現
      • 客戶端類
        • 輸入介面的UI
    • 只增加一個功能,不影響計算器原有的功能程式碼發生改變--將加減乘除等運算分離,修改其中一個不影響另外的幾個
      • Operation類
        • set 與 get 方法
        • 虛方法:GetResult()用於得到結果
      • 加減乘除類 繼承 Operation類
        • 加減乘除功能具體實現
          • 對於每一個功能重寫GetResult()方法
      • 客戶端類

現在的問題是:如何去例項話一個物件

1.簡單工廠模式--"switch-case"--類建立型模式

簡單工廠、工廠模式初學習

專門定義一個類用來負責建立其他類的例項,被建立的例項通常都具有共同的父類

public class OperationFactory {
      public static BaseOperation createOperation(String operate) {
      		  int sum = 0;
            switch (operate) {
                  case "+":
                  		 sum=new OperationAdd();
                        break;
                  case "-":
                  		 sum=new OperationSub();
                        break;
                  case "*":
                  		 sum=new OperationMul();
                        break;
                  case "/":
                  		 sum=new OperationDiv();
                        break;      
            }
            return sum ;
      }
}
複製程式碼
  • 優點
    • 工廠類是整個模式的關鍵,包含了必要的邏輯判斷,根據外界給定的資訊,決定究竟應該建立哪個具體類的物件
  • 缺點
    • 由於工廠類集中了所有例項的建立邏輯,違反了高內聚責任分配原則,將全部建立邏輯集中到了一個工廠類中;它所能建立的類只能是事先考慮到的,如果需要新增新的類,則就需要改變工廠類了。
  • 意義
    • 通過使用工廠類,外界可以從直接建立具體產品物件轉換為直接使用物件就可以了,而不必管這些物件是如何建立及如何組織的,明確了各自的職責和權利,有利於整個軟體體系結構的優化

相關借鑑: https://www.jianshu.com/p/3f824a91d73b https://juejin.im/post/59cd07eb6fb9a00a3c4b40ba

繼續閱讀的知識點補充與溫故:

1.抽象--abstract

Animal類根本就不可能例項化,一隻貓長什麼樣子可以想象,但是例項化一個動物,那麼動物長什麼樣?所以動物是一個抽象的名詞,沒有具體物件與之對應

【抽象類的注意事項】

  • 抽象類不能例項化
    • Animal例項化沒有意義
  • 抽象方法是 必須 被子類重寫 的方法
  • 如果類中包含抽象方法,那麼累就必須定義為抽象類,不論是否還包含其他一般的方法

抽象類應該擁有儘可能多的共同程式碼,擁有儘可能少的資料

設計一個抽象類時,一定是用來繼承的

簡單工廠、工廠模式初學習

如果牛、羊、狗、貓、猴是最後一級,那麼他們就是具體類,
但如果還有更下面一級的金絲猴繼承於猴,哈巴狗繼承於狗,
那就需要考慮把貓和狗改為抽象類的了
複製程式碼

2.開放-封閉原則--多擴充套件,少修改--面對物件設計的核心所在

精髓:面對需求,對程式的改動是通過增加新程式碼進行的,而不是更改現有的程式碼

  • 對於擴充是開放的
  • 對於更改是封閉的

2.工廠模式

定義一個用於建立物件的介面,讓子類決定例項化哪一個類

工廠模式使一個類的例項化延遲到其子類

簡單工廠、工廠模式初學習

簡單工廠模式 和 工廠模式 的 對比例子--雷鋒工廠

//定義一個雷鋒類
public class LeiFeng {

    public void sweep(){
        System.out.println("掃地");
    }

    public void wash(){
        System.out.println("洗衣");
    }

    public void cook(){
        System.out.println("做飯");
    }
}
複製程式碼
//學雷鋒的大學生類,繼承雷鋒  
public class Undergraduate extends LeiFeng  
{  
  
}
複製程式碼
//客戶端程式碼  
public class Main  
{  
    public static void main(String[] args)  
    {  
        LeiFeng xueleifeng = new Undergraduate(); 
        xueleifeng.buyRice(); 
        xueleifeng.sweep();  
        xueleifeng.wash();  
    }  
}  
複製程式碼
  • 現在假設有三個人要去代替他做這些事,那就應該例項化三個學雷鋒的大學生物件了
LeiFeng student1 = new Undergraduate();  
student1.buyRice();  
  
LeiFeng student2 = new Undergraduate();  
student2.sweep();  
  
LeiFeng student3 = new Undergraduate();  
student3.wash();  
複製程式碼
  • 然而不僅僅有大學生去幫助老人,還有“社群志願者”也會參與其中,那麼這樣的寫法就非常不合適了,因為我們需要更改多個例項化的地方,所以還需要增加一個繼承“雷鋒”的類 --“社群志願者”類

1.簡單工廠模式

//社群志願者  
public class Volunteer extends LeiFeng  
{  
  
}  
//簡單工廠類  
public class SimpleFactory  
{  
    public static LeiFeng createLeiFeng(String type)  
    {  
        LeiFeng result = null;  
  
        if ("學雷鋒的大學生".equals(type))  
        {  
            result = new Undergraduate();  
        }  
        else if ("社群志願者".equals(type))  
        {  
            result = new Volunteer();  
        }  
  
        return result;  
    }  
}  

//客戶端程式碼,如果要換,就只需要換“學雷鋒的大學生”為“社群志願者” 
 
LeiFeng studentA = SimpleFactory.createLeiFeng("學雷鋒的大學生");  
studentA.buyRice();  
  
LeiFeng studentB = SimpleFactory.createLeiFeng("學雷鋒的大學生");  
studentB.sweep();  
          
LeiFeng studentC = SimpleFactory.createLeiFeng("學雷鋒的大學生");  
studentC.wash();  
複製程式碼

2.工廠模式

//雷鋒工廠  
public interface IFactory  
{  
    LeiFeng createLeiFeng();  
}  
//學雷鋒的大學生工廠  
public class UndergraduateFactory implements IFactory  
{  
    public LeiFeng createLeiFeng()  
    {  
        return new Undergraduate();  
    }  
}  
//社群志願者工廠  
public class VolunteerFactory implements IFactory  
{  
    public LeiFeng createLeiFeng()  
    {  
        return new Volunteer();  
    }  
}  
//客戶端程式碼  
public class Main  
{  
    public static void main(String[] args)  
    {  
    
    
    //要換成“社群志願者”修改這裡就可以了
    //只需要修改一處就可以了,這是最佳的做法
    
    
        IFactory factory = new UndergraduateFactory();  
        LeiFeng student = factory.createLeiFeng();  
  
        student.buyRice();  
        student.sweep();  
        student.wash();  
    }  
}  
複製程式碼
  • 總結:
    • 他們都是集中封裝了物件的建立,使得要更換物件時候,不需要做大的改動就能實現,降低了客戶端與產品物件的耦合
    • 工廠模式使簡單工廠模式的進一步抽象和推廣

3.策略模式--演算法獨立於使用它的客戶而變化

  • Context: 環境類
  • Strategy: 抽象策略類
  • Strategy: 抽象策略類

它定義了演算法家族,分別封裝起來,讓他們之間可以相互替換,此模式讓演算法的變化,不會影響使用演算法的客戶。

參考:http://hjxandhmr.github.io/2016/06/10/DesignPattern-Strategy/

相關文章