借鑑 :《大話資料結構》 http://www.cnblogs.com/cj723/
活字印刷--物件導向
活字印刷,即當需要改變部分字的時候,不需要整個刻板全部重新刻,解耦。
- 可維護
- 要改,只需更改要改之字
- 可複用
- 這些字並非這次用完就無用,完全可以後來的印刷中重複使用
- 可擴充套件
- 若需要在已有內容里加字,只需要另刻字加入即可
- 靈活性好
- 子的排版可能是豎排也可能是橫排,需求改變時只需要將活字移動就克做到滿足排列需求
所以需要通過 封裝、繼承、多型把程式的耦合度降到最低
- 業務的封裝
- 將業務邏輯與介面邏輯分開,讓他們之間的耦合度下降
- 比如一個Windows計算器,將計算和顯示分開
- Operation運算類
- 加減乘除功能具體實現
- 客戶端類
- 輸入介面的UI
- Operation運算類
- 只增加一個功能,不影響計算器原有的功能程式碼發生改變--將加減乘除等運算分離,修改其中一個不影響另外的幾個
- Operation類
- set 與 get 方法
- 虛方法:GetResult()用於得到結果
- 加減乘除類 繼承 Operation類
- 加減乘除功能具體實現
- 對於每一個功能重寫GetResult()方法
- 加減乘除功能具體實現
- 客戶端類
- Operation類
現在的問題是:如何去例項話一個物件
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/