接下來要講到所謂的設計模式
其實到設計模式後面我聽了覺得很硬
加上身體不適腦袋一直空轉
所以有講錯的地方請大力給我鞭下去(我會馬上修正)
在講這個之前先來回想一下前面幾張講到的繼承
其實繼承並非大家眼中看到的這麼美好
繼承也是有缺點在的
其實繼承並非大家眼中看到的這麼美好
繼承也是有缺點在的
缺點
1、由於衍生類別必須具有基底類別的所有特性,會增加 衍生類別的約束
2、衍生類別會強耦和基底類別,當基底類別被修改也會 影響衍生類別
舉例
在父類別多新增一個 virtual方法,那麼子類別就要override這個方法
所以繼承的關係,最多建議到三層就好,因為繼承的深度越深,要改的地方就會越多
假設
A:B
B:C
C:D
一旦 C 改變C以前的都要改
如果是 D改變 D以前的都要改
所以深度越深,要改的東西就可能越多
1、由於衍生類別必須具有基底類別的所有特性,會增加 衍生類別的約束
2、衍生類別會強耦和基底類別,當基底類別被修改也會 影響衍生類別
舉例
在父類別多新增一個 virtual方法,那麼子類別就要override這個方法
所以繼承的關係,最多建議到三層就好,因為繼承的深度越深,要改的地方就會越多
假設
A:B
B:C
C:D
一旦 C 改變C以前的都要改
如果是 D改變 D以前的都要改
所以深度越深,要改的東西就可能越多
SOLID 六大原則
單一職責原則:就一個類別而言,應該僅有一個引起它變化的原因
里式替換原則:軟體使用父類別的地方,一定也會適用於子類別
倚賴倒置原則:高層模組不應倚賴低層模組,兩者都應該倚賴抽象
抽象不應該倚賴細節,細節應該倚賴抽象
介面隔離原則:客戶端不應該倚賴它不需要的介面 ,類別間的倚賴應建立在最小的介面上
開閉原則 : 對擴展開放,對修改封閉
最少知識原則 (迪米特法則) :一個物件應該對其他物件有最少了解
單一職責原則:就一個類別而言,應該僅有一個引起它變化的原因
里式替換原則:軟體使用父類別的地方,一定也會適用於子類別
倚賴倒置原則:高層模組不應倚賴低層模組,兩者都應該倚賴抽象
抽象不應該倚賴細節,細節應該倚賴抽象
介面隔離原則:客戶端不應該倚賴它不需要的介面 ,類別間的倚賴應建立在最小的介面上
開閉原則 : 對擴展開放,對修改封閉
最少知識原則 (迪米特法則) :一個物件應該對其他物件有最少了解
IoC控制反轉
其實控制反轉在字面上比較難理解
我們把它看成控制權移轉,就是把控制權給別人
不讓自己本身來決定自己要幹嘛
接下來帶大家來看程式碼應該就能很快理解了
其實控制反轉在字面上比較難理解
我們把它看成控制權移轉,就是把控制權給別人
不讓自己本身來決定自己要幹嘛
接下來帶大家來看程式碼應該就能很快理解了
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//這是還沒用Ioc的設計方式
namespace IoCSample.NoneIoC
{
public class Benz
{
public void WhoIs()
{
Console.WriteLine("I am Benz");
}
}
public class BMW
{
public void WhoIs()
{
Console.WriteLine("I am BMW");
}
}
}
static void Main(string[] args)
{
//非 IOC 呼叫, 上層類別 (Program) 直接倚賴實作, 而且由 Program 決定實做類別
var car = new NoneIoC.Benz();
car.WhoIs();
Console.ReadLine();
}
這邊很重要,所以一定要注意看清楚我寫的文字
現在問題來了,請問各位,目前決定 var car 變數內存放什麼東西
是靠誰來決定? 靠等號右邊 new 什麼給他對吧??
所以今天我放 Benz 他就是賓士
如果我要改成BMW怎麼辦????
是不是要進入到
static void Main(string[] args)
{
}
這個方法內去改?
改成 var car = new NoneIoC.BMW(); 對吧???
所以你目前依賴的是實體
假設你有20個地方都這樣寫
var car = new NoneIoC.Benz();
客戶今天說 我要改成開Toyota
那你不是要改20次
var car = new NoneIoC.BMW() => var car = new NoneIoC.Toyota()
這樣你不痛苦嗎???
你保證你都會全部改到,不會漏改?
所以沒有使用Ioc的狀況下
你把控制權放在自己身上,依賴實體,每當需求改變
你就會改到死,說不定還不能準時下班
若我們使用IoC的方式會如何?直接來看Code吧
現在問題來了,請問各位,目前決定 var car 變數內存放什麼東西
是靠誰來決定? 靠等號右邊 new 什麼給他對吧??
所以今天我放 Benz 他就是賓士
如果我要改成BMW怎麼辦????
是不是要進入到
static void Main(string[] args)
{
}
這個方法內去改?
改成 var car = new NoneIoC.BMW(); 對吧???
所以你目前依賴的是實體
假設你有20個地方都這樣寫
var car = new NoneIoC.Benz();
客戶今天說 我要改成開Toyota
那你不是要改20次
var car = new NoneIoC.BMW() => var car = new NoneIoC.Toyota()
這樣你不痛苦嗎???
你保證你都會全部改到,不會漏改?
所以沒有使用Ioc的狀況下
你把控制權放在自己身上,依賴實體,每當需求改變
你就會改到死,說不定還不能準時下班
若我們使用IoC的方式會如何?直接來看Code吧
namespace IoCSample.IoC
{
//首先建立一個介面
//讓Benz 跟 BMW 都繼承並且各自實作
public interface ICar
{
void WhoIs();
}
internal class Benz : ICar
{
public void WhoIs()
{
Console.WriteLine("I am Benz");
}
}
internal class BMW : ICar
{
public void WhoIs()
{
Console.WriteLine("I am BMW");
}
}
//這在邊卡一個工廠,這個工廠來決定 new出來的對向是誰
//所以這邊我把控制權給了 public class CarFactory
public class CarFactory
{
public static ICar GetCar()
{
return new BMW();
}
}
}
static void Main(string[] args)
{
var car = IoC.CarFactory.GetCar();//如果你每個地方都這樣寫
car.WhoIs(); //客戶如果現在說要開賓士
Console.ReadLine(); //假設你有20個地方都這樣寫
//20個地方都不用改
//只要改public class CarFactory的GetCar方法
//改成 return new Benz ();
}
所以現在我們已經把控制權移轉到 public class CarFactory的 GetCar( )
不用再去一個一個改 var car = new NoneIoC.BMW() => var car = new NoneIoC.Bezn()
所以我們在設計上多卡這一層
在修改上是不是大大提升速度,也保證不會漏改?
不用再去一個一個改 var car = new NoneIoC.BMW() => var car = new NoneIoC.Bezn()
所以我們在設計上多卡這一層
在修改上是不是大大提升速度,也保證不會漏改?