新聞中心
最近在看七牛云許式偉的架構(gòu)課, 重溫了面向?qū)ο笪宕笤O(shè)計(jì)原則(SOLID)。(當(dāng)然許老板是不可能深聊這么低級(jí)的內(nèi)容)。

永州網(wǎng)站建設(shè)公司成都創(chuàng)新互聯(lián)公司,永州網(wǎng)站設(shè)計(jì)制作,有大型網(wǎng)站制作公司豐富經(jīng)驗(yàn)。已為永州千余家提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\成都外貿(mào)網(wǎng)站建設(shè)公司要多少錢(qián),請(qǐng)找那個(gè)售后服務(wù)好的永州做網(wǎng)站的公司定做!
注意區(qū)分設(shè)計(jì)原則和設(shè)計(jì)模式。設(shè)計(jì)原則更為抽象和泛化;設(shè)計(jì)模式也是抽象或泛化的良好實(shí)踐,但是它們提供了更具體和實(shí)用的底層建議。
|
面 as 向?qū)ο?大原則 |
|
|
Single Responsiblity Principle |
單一職責(zé)原則 |
|
Open/Closed Principle |
開(kāi)閉原則 |
|
Likov Substitution Principle |
里斯替代原則 |
|
Interface Segregation Principle |
接口隔離原則 |
|
Dependency inversion |
依賴倒置原則 |
單一職責(zé)原則
只能有一個(gè)讓組件或類發(fā)生改變的原因;或者說(shuō)每個(gè)組件或類專注于單一功能,解決特定問(wèn)題。
there should never be more than one reason for a class to change. A class should be focused on a single functionality, address a specific concern.
開(kāi)閉原則
對(duì)擴(kuò)展開(kāi)放, 對(duì)修改封閉。
擴(kuò)展類的幾種方式:
- 從類繼承
- 類中重寫(xiě)同名行為
- 擴(kuò)展類的某些行為
一般我們通過(guò)繼承或者實(shí)現(xiàn)接口來(lái)實(shí)踐開(kāi)閉原則。
class Person
{
public int age;
public string name;
public Person(string name, int age)
{
this.name = name;
this.age = age;
}
public virtual void SayHallo()
{
Console.WriteLine("我是{0},今年{1}", name, age);
}
}
class Student : Person
{
public string major;
public Student(string name, int age, string major) : base(name, age)
{
this.major = major;
}
public override void SayHallo() //子類中override重寫(xiě),實(shí)現(xiàn)虛方法
{
Console.WriteLine("我是{0},今年{1},正在學(xué)習(xí){2}", name, age, major);
}
}
class Program
{
static void Main(string[] args)
{
Person trevor1 = new Person("Trevor", 18);
trevor1.SayHallo();
Student trevor2 = new Student("Trevor", 18,"C#");
trevor2.SayHallo();
}
}
output:
我是Trevor,今年18
我是Trevor,今年18,正在學(xué)習(xí)C#
里氏替代原則
在父子類生態(tài)中,在父類出現(xiàn)的地方,可以用子類對(duì)象替換父類對(duì)象,同時(shí)不改變程序的功能和正確性。
。。 乍一看,這不是理所當(dāng)然嗎?
為啥單獨(dú)拎出來(lái)鞭尸,鞭策。
比如上例我們使用
Person trevor1 = new Student("trevor",18,"C#") // 子類對(duì)象替換父類對(duì)象
trevor1.SayHello();利用多態(tài)正確表達(dá)了含義。
但是某些情況下濫用繼承,卻不一定保證程序的正確性,會(huì)對(duì)使用者造成誤解。
比如下面經(jīng)典的[矩形-正方形求面積]反例:
public class Rectangle
{
// 分別設(shè)置寬高
public virtual double Width {get;set;}
public virtual double Height {get;set;}
public virtual void Area()
{
Console.WriteLine("面積是:" + Width * Height);
}
}
public class Square : Rectangle
{
public override double Width
{
// get;
set // 因?yàn)槭钦叫危氘?dāng)然重設(shè)了寬=高
{
base.Width= value;
base.Height= value;
}
}
public override double Height
{
// get;
set // 因?yàn)槭钦叫?,想?dāng)然重設(shè)了寬=高
{
base.Width = value;
base.Height = value;
}
}
public override void Area()
{
Console.WriteLine("面積是:" + Width * Width);
}
}
public class Program
{
public static void Main()
{
Rectangle s = new Rectangle();
s.Width = 2;
s.Height = 3;
s.Area();
}
}
output:
面積是:6
但是如果你[使用子類對(duì)象去替換父類對(duì)象]:
Rectangle s2 = new Square();
s2.Width = 2;
s2.Height = 3;
s2.Area();
output:
面積是:9
Get到了嗎?我們不能想當(dāng)然的認(rèn)為子類對(duì)象就能無(wú)損替換父類對(duì)象, 根本原因是我們正方形雖然是(is a)矩形,但是我們的重寫(xiě)行為破壞了父類的表達(dá),這是一種繼承的誤用。
里氏替代原則就是約束你在繼承(is a)的時(shí)候注意到這個(gè)現(xiàn)象,并提醒你規(guī)避這個(gè)問(wèn)題。
這個(gè)時(shí)候,不應(yīng)該重寫(xiě)父類的SetWight方法, 而應(yīng)該擴(kuò)展新的方法SetLength。
接口隔離
將胖接口修改為多個(gè)小接口,調(diào)用接口的代碼應(yīng)該比實(shí)現(xiàn)接口的代碼更依賴于接口。
why:如果一個(gè)類實(shí)現(xiàn)了胖接口的所有方法(部分方法在某次調(diào)用時(shí)并不需要),那么在該次調(diào)用時(shí)我們就會(huì)發(fā)現(xiàn)此時(shí)出現(xiàn)了(部分并不需要的方法),而并沒(méi)有機(jī)制告訴我們現(xiàn)在不應(yīng)該使用這部分方法。
how:避免胖接口,不要實(shí)現(xiàn)違反單一職責(zé)原則的接口。可以根據(jù)實(shí)際多職責(zé)劃分為多接口,某個(gè)類實(shí)現(xiàn)多接口后, 在調(diào)用時(shí)以特定接口指代對(duì)象,這樣這個(gè)對(duì)象只能體現(xiàn)特定接口的方法,以此體現(xiàn)接口隔離。
public interface IA
{
void getA();
}
interface IB
{
void getB();
}
public class Test : IA, IB
{
public string Field { get; set; }
public void getA()
{
throw new NotImplementedException();
}
public void getB()
{
throw new NotImplementedException();
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
IA a = new Test();
a.getA(); // 在這個(gè)調(diào)用處只能看到接口IA的方法, 接口隔離
}
}
依賴倒置原則
實(shí)現(xiàn)依賴于抽象, 抽象不依賴于細(xì)節(jié)。
Q:這個(gè)原則我其實(shí)一開(kāi)始沒(méi)能理解什么叫“倒置”?
A: 但有了一點(diǎn)開(kāi)發(fā)經(jīng)驗(yàn)后開(kāi)始有點(diǎn)心得了。
痛點(diǎn):面向過(guò)程的開(kāi)發(fā),上層調(diào)用下層,上層依賴于下層。當(dāng)下層變動(dòng)時(shí)上層也要跟著變動(dòng),導(dǎo)致模塊復(fù)用度降低,維護(hù)成本增高。
提煉痛點(diǎn):含有高層策略的模塊,如AutoSystem模塊,依賴于它所控制的低層的負(fù)責(zé)具體細(xì)節(jié)的模塊。
思路:找到一種方法使AutoSystem模塊獨(dú)立于它所控制的具體細(xì)節(jié),那么我們就可以自由地復(fù)用AutoSystem了;同時(shí)讓底層汽車廠也依賴抽象,受抽象驅(qū)動(dòng),這就形成一種“倒置”。
所以依賴倒置原則有兩個(gè)關(guān)鍵體現(xiàn):
① 高層次模塊不應(yīng)該依賴于低層實(shí)現(xiàn),而都應(yīng)該依賴于抽象;
這在上圖:AutoSystem和Car都依賴于抽象接口ICar
② 抽象不應(yīng)該依賴于具體實(shí)現(xiàn),具體實(shí)現(xiàn)應(yīng)該依賴于抽象。
第2點(diǎn)與第1點(diǎn)不是重復(fù)的,這一點(diǎn)意味著細(xì)節(jié)實(shí)現(xiàn)是受抽象驅(qū)動(dòng),這也是“倒置”的由來(lái), 這一點(diǎn)是通過(guò)接口叫ICar而不是IAutoSystem來(lái)體現(xiàn)。
面相對(duì)象五大設(shè)計(jì)原則SOLID,是指導(dǎo)思想,不貫徹這5大設(shè)計(jì)原則也能讓程序跑起來(lái),但是可能就會(huì)出現(xiàn)閱讀性、維護(hù)性、正確性問(wèn)題。
網(wǎng)頁(yè)標(biāo)題:面向?qū)ο笪宕笤O(shè)計(jì)原則,你學(xué)會(huì)了嗎?
文章網(wǎng)址:http://www.fisionsoft.com.cn/article/djhpjoh.html


咨詢
建站咨詢
