開閉原則(OCP) 詳解
基本介紹:
1)開閉原則(Open Close Principle)是程式設計中最基礎,最重要的設計原則
2)一個軟體實體如類,子產品和函數應該對拓展開放(對提供方),對修改關閉(對使用方)。用抽象建構架構,用實作擴充細節。
3)當軟體需要變化時,盡量通過擴充軟體實體的行為來實作變化,而不是通過修改已有的代碼來實作變化。
4)程式設計中遵循其它原則,以及使用設計模式的目的就是遵循開閉原則。
案例舉例:
public interface MailService {
void sendMsg(String msg);
}
首先我們定義一個功能性接口,表示資訊服務,裡面有個發送資訊的方法。
public class DefaultMailService implements MailService{
@Override
public void sendMsg(String msg) {
// TODO Auto-generated method stub
System.out.println("message:"+msg);
}
}
以及它的測試類:
public class MailServiceTest {
static MailService mailService;
public static void main(String[] args) {
mailService=new DefaultMailService();
mailService.sendMsg("nihao");
}
}
接着我們在它的實作類中實作發送資訊的方法。
假如說我們已經将其功能實作完畢。等過一段時間,我們需要對此業務進行擴充,要求顯示出發送資訊的時間。其中的一種寫法便是在DefaultMailService類中直接修改:
public class DefaultMailService implements MailService{
@Override
public void sendMsg(String msg) {
// TODO Auto-generated method stub
long start = System.currentTimeMillis();
System.out.println("message:"+msg);
long end = System.currentTimeMillis();
System.out.println("time:"+(end-start));
}
}
但是很顯然,根據開閉原則,這種做法在實際的項目中是不可取的,應當滿足對拓展開放,對修改關閉。
對于此,我們有兩種解決辦法:
第一種:通過寫一擴充類繼承實作類進行實作類功能的擴充:
建立一LogMailService類繼承DefaultMailService類并重寫其方法:
public class LogMailService extends DefaultMailService{
DefaultMailService defaultMailService;
public LogMailService(DefaultMailService defaultMailService) {
this.defaultMailService=defaultMailService;
}
@Override
public void sendMsg(String msg) {
// TODO Auto-generated method stub
long start = System.currentTimeMillis();
super.sendMsg(msg);
long end = System.currentTimeMillis();
System.out.println("time:"+(end-start));
}
}
在其子類中對sendMsg功能進行了擴充
測試類修改:
public class MailServiceTest {
static MailService mailService;
public static void main(String[] args) {
mailService=new LogMailService(new DefaultMailService());
mailService.sendMsg("nihao");
}
}
但是這種方法在某些情況下不能使用,比如當defaultMailService用final修飾時,此類便不能被繼承。
第二種方法:通過寫擴充類組合于實作類進行功能的擴充
建立一Log2MailService擴充類實作MailService接口:
public class Log2MailService implements MailService{
DefaultMailService defaultMailService;
public Log2MailService(DefaultMailService defaultMailService) {
this.defaultMailService=defaultMailService;
}
@Override
public void sendMsg(String msg) {
// TODO Auto-generated method stub
long start = System.currentTimeMillis();
defaultMailService.sendMsg(msg);
long end = System.currentTimeMillis();
System.out.println("time:"+(end-start));
}
}
實作類修改:
public class MailServiceTest {
static MailService mailService;
public static void main(String[] args) {
mailService=new Log2MailService(new DefaultMailService());
mailService.sendMsg("nihao");
}
}
思路解析圖: