溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

開放封閉原則_動力節(jié)點Java學(xué)院整理

發(fā)布時間:2020-08-29 12:45:04 來源:腳本之家 閱讀:136 作者:yysyangyangyangshan 欄目:編程語言

定義:軟件實體(類、模塊、函數(shù)等)應(yīng)該是可以擴展的,但是不可修改。對于擴展是開放的,對于更改是封閉的。關(guān)鍵是抽象,將一個功能的通用部分和實現(xiàn)細節(jié)部分清晰的分離開來。

這里要求我們寫代碼要有抽象的概念。什么是抽象?指由實體抽離出概念的思考過程。就是從眾多的對象中抽離出共同的本質(zhì)的特征。在寫代碼的過程中,需要抽象類的地方,只需要抓住這個類的本質(zhì)功能,不要老想著它在這個工程中的具體功能。

我們繼續(xù)看開放封閉原則,這個原則要求,將一個功能的共用部分和實現(xiàn)部分清晰地分離開來。因為在最初搭建架構(gòu)的時候你不能預(yù)測到所有將要發(fā)生的變化,那么這個類也就不是一塵不變的,隨著在各個模塊中具體實現(xiàn)的時候,你發(fā)現(xiàn)抽象的類適合這個功能,但是對另一個功能又不適合。那么是否要返回去修改抽象類呢?這個代價是很大的,需要重新全盤思考,還要調(diào)整具體細節(jié)。如果程序還沒發(fā)布還好一些,一旦程序發(fā)布了,那么返回修改抽象類,影響將更大。所以在開始抽象的時候就要防止這樣的現(xiàn)象發(fā)生,要遵循開放封閉原則。抽象類、接口是一種標(biāo)準(zhǔn),在程序中一旦定義好,就不能輕易去修改,需求有變化,怎么辦呢?可以擴展這個接口,重寫方法,或者繼承后增加新的方法,但是一定不要去修改。

下面用兩個例子來說明開放封閉原則。

1、連接數(shù)據(jù)庫為例。

比如在程序中用到的不同類型的數(shù)據(jù)庫連接,Access和Oracle。直接連接如下:

class ConnectAccess 
{ 
  public string ConnectString() 
  { 
    string dataPath = "數(shù)據(jù)庫路徑"; 
    return string.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Persist Security Info=True;Jet OLEDB:Database Password={1}", dataPath, "密碼"); 
  } 
} 
class ConnectOracle 
{ 
  public string ConnectString() 
  { 
    return @"server=localhost;database=命名空間;uid=用戶名;pwd=密碼"; 
  } 
} 

調(diào)用

static void Main(string[] args) 
 { 
   //連接Access 
  ConnectAccess connAccess = new ConnectAccess(); 
 
  OleDbConnection accessConnection = new OleDbConnection(connAccessConnectString()); 
 
   //連接Oracle 
  ConnectOracle connOracle = new ConnectOracle(); 
 
  OracleConnection oracleConnection = new OracleConnection(connOracleConnectString()); 
 } 

這樣每次都要去考慮OleDbConnection的參數(shù)到底用哪個。下面修改一下。抽象一個接口。

interface ConnectDataBase 
{ 
  string ConnectString(); 
} 
 
class ConnectAccess : ConnectDataBase 
{ 
  #region ConnectDataBase 成員 
 
  public string ConnectString() 
  { 
    string dataPath = "數(shù)據(jù)庫路徑"; 
 
    return stringFormat("Provider=MicrosoftJetOLEDB0;Data Source={0};Persist Security Info=True;Jet OLEDB:Database Password={1}", dataPath, "密碼"); 
  } 
 
  #endregion 
} 
 
class ConnectOracle : ConnectDataBase 
{ 
  #region ConnectDataBase 成員 
 
  public string ConnectString() 
  { 
    return @"server=localhost;database=命名空間;uid=用戶名;pwd=密碼"; 
  } 
 
  #endregion 
} 

調(diào)用

static void Main(string[] args) 
{ 
  ConnectDataBase conn = null; 
 
  //連接Access 
  conn = new ConnectAccess(); 
 
  OleDbConnection accessConnection = new OleDbConnection(connConnectString()); 
 
  //連接Oracle 
  conn = new ConnectOracle(); 
 
  OracleConnection oracleConnection = new OracleConnection(connConnectString()); 
} 

改過后,只需關(guān)心conn用哪一個類實例化,就可以了。不過大家可能看到,由于Oracle的連接必須OracleConnection,可能優(yōu)勢不容易看出來。

2、基本類型作為方法參數(shù)為例。

一般的設(shè)計原則之所以強調(diào)方法參數(shù)盡量避免基本類型,原因正在于此。比較如下兩個方法定義:

//定義1  
bool Connect(string userName, string password, string wifiAddress, int port) 
{ 
  return false; 
} 
//定義2  
bool Connect(Account account) 
{ 
  return false; 
} 
public class Account 
{ 
  public string UserName 
  { 
    get; 
    set; 
  } 
  public string Password 
  { 
    get; 
    set; 
  } 
  public string WifiAddress 
  { 
    get; 
    set; 
  } 
  public int Port 
  { 
    get; 
    set; 
  } 
} 

相比較而言,定義2多了一個Account類的定義,Connect()方法明顯更加穩(wěn)定。如果Connect()方法wifiAddress發(fā)生改變,定義1必須修改該方法的接口,對應(yīng)的,所有調(diào)用Connect()方法的對象都會受到影響;而定義2只需要修改Account類,由于Connect()方法的接口保持不變,而對于Connect()方法的調(diào)用者并不需wifiAddress,這樣的修改就完全不會影響調(diào)用者,從而降低需求變化帶來的影響。

總之開放封閉原則最關(guān)鍵的是抽象,但是也并不是說一旦抽象接口、類確定就一定不能修改。只是,我們在抽象的時候就要全面思考,爭取做到不用修改,一旦需求有變化,只需在實現(xiàn)的時候有變動。當(dāng)然,需求是千變?nèi)f化的,一旦需要改動抽象的部分,那么只要前面嚴(yán)格遵循了該原則,影響也會小得多。當(dāng)然了如果修改了,一定要進行單元測試,凡是用到的地方都要測試正確。

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI