本文
1、內聚(Cohesion)
- 把功能所需要的資料與程式都塞在某一個模組(fuction、class、package)中,使得該模組成為一個單獨的可執行個體。
大意上就是把程式跟所需要的資料全部都包在一起。
舉例:(不要懷疑我們最熟悉的特斯拉又來了)
今天我想要讓特斯拉具備螢幕、音響這些娛樂設施可以看電影,有了電影當然需要食物啊,那就需要有在特斯拉上吃爆米花的功能。
//產生一個特斯拉類別有螢幕、音響、吃爆米花
public class 特斯拉
{
public string 螢幕()
{
return "播放電影";
}
public string 音響()
{
return "杜比環繞音效";
}
public string 吃爆米花()
{
return "爆米花好吃";
}
}
private static void Main(string[] args)
{
特斯拉 Tesla = new 特斯拉();
Console.WriteLine("特斯拉 :" + Tesla.螢幕());
Console.WriteLine("特斯拉開啟 :" + Tesla.音響());
Console.WriteLine(Tesla.吃爆米花());
}
這時候要提到程式設計常聽到的。
高內聚
- 高內聚力的好處就是提高了模組的『獨立性』,也就是說這個模組可以被單獨使用,也可以被單獨修改。
那應該怎麼做呢?
- 思考模組的關聯性。
以我們剛剛舉的例子特斯拉具備螢幕、音響這些娛樂設備是合理的,但吃爆米花的動作是不是在這個 Class 中顯得有點怪異了呢?
- 特斯拉本身並不需要知道怎麼吃爆米花,需要知道怎麼吃爆米花的是人。
我們修改一下範例
//產生一個特斯拉類別有螢幕、音響
public class 特斯拉
{
public string 螢幕()
{
return "播放電影";
}
public string 音響()
{
return "杜比環繞音效";
}
}
//產生一個人類別有吃爆米花的動作
public class 人
{
public string 吃爆米花()
{
return "爆米花好吃";
}
}
private static void Main(string[] args)
{
特斯拉 Tesla = new 特斯拉();
Console.WriteLine("特斯拉 :" + Tesla.螢幕());
Console.WriteLine("特斯拉開啟 :" + Tesla.音響());
人 Human = new 人();
Console.WriteLine("人在特斯拉上吃爆米花覺得:" + Human.吃爆米花());
}
獨立出了特斯拉與人兩個 Class,特斯拉以後可以再加裝 KTV 設備,而人也可以增加唱歌這個動作,兩個模組具備自己的主題且獨立運作,亦可以獨立被使用。
2、耦合(Coupling)
- Coupling(耦合):如果某個模組跟『其他人(另一個模組)』有關係(例如,使用 global variables 或是接受其他模組傳入的參數)那麼這兩個模組就彼此耦合。
簡單來說就是程式之間的關聯性。
2020/07/20 修改範例,跟同事聊完後,發現舉例不夠藕(?
舉例:今天特斯拉必須要有駕駛才能上路。
//產生一個特斯拉類別有上路的功能
public class 特斯拉
{
public string 上路(駕駛 driver)
{
return driver.司機();
}
}
//產生一個駕駛類別有一位司機
public class 駕駛
{
public string 司機()
{
return "一位司機";
}
}
private static void Main(string[] args)
{
駕駛 driver = new 駕駛();
特斯拉 Tesla = new 特斯拉();
Console.WriteLine($"特斯拉上路有{Tesla.上路(driver)}");
}
上述例子特斯拉就跟駕駛這個類別產生高度藕和的關係,當我想要將駕駛這個類別加入新東西時,特斯拉就會受到影響。
這時候又可以提到另一個觀念。
低耦合
要怎麼降低這個範例程式的耦合度呢?
我們可以將駕駛這個類別改成介面。
//產生一個駕駛介面
public interface Idriver
{
public string 駕駛();
}
//產生一個特斯拉類別有上路的功能並繼承駕駛介面
public class 特斯拉 : Idriver
{
public string 上路()
{
return this.駕駛();
}
//實作駕駛這個類別
public string 駕駛()
{
return "人類司機";
}
}
private static void Main(string[] args)
{
特斯拉 Tesla = new 特斯拉();
Console.WriteLine($"特斯拉上路有{Tesla.上路()}");
}
如此一來特斯拉不直接依賴於駕駛,改成依賴於介面就降低了耦合度,今天特斯拉技術成長快速,真的能實際自動駕駛上路時我們也可以將駕駛抽換成自動駕駛如下…
//產生一個駕駛介面
public interface Idriver
{
public string 駕駛();
}
//產生一個特斯拉類別有上路的功能並繼承駕駛介面
public class 特斯拉 : Idriver
{
public string 上路()
{
return this.駕駛();
}
//實作駕駛這個類別
public string 駕駛()
{
return "自動駕駛";
}
}
private static void Main(string[] args)
{
特斯拉 Tesla = new 特斯拉();
Console.WriteLine($"特斯拉上路有{Tesla.上路()}");
}
高內聚、低耦合最終目的
- 需求異動容易抽換、修改與增加功能,而不會對太多既存功能造成影響。
- 每個功能重用性高、擴展性好、維護性高。