设计原则之开放闭合原则(OCP)

在《敏捷软件开发-原则、模式与实践》一书中,对开放闭合原则的定义为:

软件实体(类、模块、函数等)应该是可以扩展的,但是不可以修改。

简言之,两个特征:

1、对于扩展是开放的;

2、对于修改是关闭的

这两点特征貌似自相矛盾,怎么样在不改动模块源码的情况下去更改他的行为呢?如果不更改一个模块,又怎么能够去改变它的功能呢?

答案很简单,就是抽象。模块可能对抽象体进行操作。由于模块依赖于一个固定的抽象体,所以他对于更改可以是封闭的。同时,通过从这个抽象体去派生,可以扩展此模块的行为。

设计原则开篇一文中已经举例说明了如何应用这个原则。在这篇文章中再举一个例子,帮助大家加深认识。

如果你有去看zend framework的源码,其中有一段代码是用来解析配置文件的,这次就拿这个案例来举例。

version1:

有多个配置文件:config.php、config.json、config.xml

config.php:

<?php

return array(
	'database' => array(
			'host' => '127.0.0.1',
			'username' => 'root',
			'password' => '',
			'dbname' => 'test'
		)
);

config.json:

{
	"database":{
		"host":"127.0.0.1",
		"username":"root",
		"password":"",
		"dbname":"test"
	}
}

config.xml:

<?xml version="1.0" encoding="ISO-8859-1"?>
<config>
	<database>
		<host>127.0.0.1</host>
		<username>root</username>
		<password></password>
		<dbname>test</dbname>
	</database>
</config>

我们将配置文件交给config类去处理:

public function configToArray($configFile){
     	$extension = pathinfo($configFile, PATHINFO_EXTENSION);
     	$config = array();
		switch ($extension) {
		 	case 'php':
		 		$config = require_once $configFile;
		 		break;

		 	case 'xml':
		 		$config = require_once $configFile;
		 		break;

		 	case 'json':
		 		$config = json_decode(file_get_contents($configFile), true);
		 		break;
		 }
		 foreach ($config as $key => $value) {
		 	$this->set($key, $value);
		 }
     }

这样的弊端在于,后期如果希望使用新的配置文件,比如ini文件、yaml文件等,我们就需要到switch语句里面去新增case。

现在来看version 2的设计:

首先声明了一个接口Configuration:

<?php

interface Configuration{
    public function toArray($configFilePath);
}

然后新增了3个具体的实现类:

jsonConfiguration.php

<?php
require_once "configuration.php";
class JsonConfiguration implements Configuration{
    public function toArray($configFilePath){
        return json_decode(file_get_contents($configFilePath), true);
    }
}

phpConfiguration.php

<?php
require_once "configuration.php";
class phpConfiguration implements Configuration{
    public function toArray($configFilePath){
        $config = require_once $configFilePath;
        return $config;
    }
}

xmlConfiguration.php

<?php
require_once "configuration.php";
class XmlConfiguration implements Configuration{
    public function toArray($configFilePath){
        $xml = simplexml_load_file($configFilePath);
        return json_decode(json_encode($xml), true);
    }
}

这样config类中的代码就可以修改为:

public function configToArray(Configuration $configuration){
     	$config = is_array($configuration->toArray($this->configFilePath)) ? $configuration->toArray($this->configFilePath) : array();
		 foreach ($config as $key => $value) {
		 	$this->set($key, $value);
		 }
     }

这样我们想再增加一个配置文件时,就可以新增一个实现类就可以了。也就做到了“对修改关闭,对扩展开放”了。

这个案例和设计原则开篇一文中提到的案例非常相似,可以概括为“如何将if/else转换为抽象”和“如何将iswitch转换为抽象”,

在许多方面,OCP都是面向对象设计的核心所在。遵循这个原则可以带来面向对象技术所声称的巨大好处:灵活性、可重用性和可维护性。然而,并不是说只要使用一种面向对象语言就是遵循了这个原则。对于应用程序中的每个部分都肆意地进行抽象同样不是一个好主意。正确的做法是,开发人员应该仅仅对程序中呈现出频繁变化的那些部分做出抽象。拒绝不成熟的抽象和抽象本身一样重要。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-07 16:26:18

设计原则之开放闭合原则(OCP)的相关文章

面向对象原则之一 开放封闭原则(开闭原则)

原文:面向对象原则之一 开放封闭原则(开闭原则) 前言 面向对象有人分为五大原则,分别为单一职责原则.开放封闭原则.依赖倒置原则.接口隔离原则.里氏替换原则. 也有人分为六大原则,分别为单一职责原则.开放封闭原则.依赖倒置原则.接口隔离原则.里氏替换原则.迪米特法则. 现在我们来介绍开放封闭原则,也叫开闭原则 开闭原则 1)概念 官方说法是 软件实体(模块.类.函数等)应该可以扩展,但是不可以修改.也就是说软件对扩展开放,对修改关闭. 需要说明的是,对修改关闭不是说软件设计不能做修改,只是尽量不

三、单一职责原则、开放-封闭原则、依赖倒转原则

一.单一职责原则 1.定义:就一个类而言,应该仅有一个引起它变化的原因. 2.为什么要?:如果一个类承担的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会削弱或者抑制这个类完成其他职责的能力.这种耦合会导致脆弱的设计,当变化发生时,设计会遭受到意想不到的破坏. 3.软件设计真正要做的许多内容,就是发现职责并把职责相互分离. 如果你能想到多余一个动机去改变一个类,那么这个类就具有多于一个原则. 4.示例:设计俄罗斯方块的游戏 可以分为游戏逻辑和界面表示逻辑. 游戏逻辑--数组每一项的值改

大话设计模式1.0.2-----策略模式 单一职责原则 和 开放-封闭原则

大话设计模式第二章之:策略模式 算法之间可以互相调用 策略模式就是用来封装算法的. 大话设计模式第三章之:单一职责原则 单一职责原则:就一个类而言,应该仅有一个引起它变化的原因 类承担的职责不能过多,因为有时,完成一个职责,会影响到其他职责的, 手机只用来接电话,相机只用来拍照,功能才强大,集成太多了,其他功能就弱化了. 对应一些问题,要方法化,要类分离化 大话设计模式第四章之:开放-封闭原则 开放-封闭原则:是说软件实体(类.模块.函数等等)应该可以扩展,但是不可修改.OCP 扩展是开放的,修

[Python设计模式] 第3~5章 单一职责原则/开放-封闭原则/依赖倒转原则

单一职责原则 就一个类而言,应该仅有一个引起它变化的原因. 如果一个类承担的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会削弱或者抑制这个类完成其他职责的能力.这种耦合会导致脆弱的设计,当变化发生时,设计会遭受到意想不到的破坏. 软件设计真正要做的许多内容,就是发现职责并把哪些职责相互分离.如果你能够想到多余一个的动机去改变一个类,那么这个类就具有多余一个的职责,就应该考虑类的职责分离. 开放-封闭原则 开放-封闭原则,是说软件实体(类,模块,函数等)应该可以扩展,但是不可修改.即对

面向对象编程之开放闭合原理的

开放封闭原则(OCP,Open Closed Principle)是所有面向对象原则的核心.软件设计本身所追求的目标就是封装变化.降低耦合,而开放封闭原则正是对这一目标的最直接体现. 关于开放封闭原则,其核心的思想是: 软件实体应该是可扩展,而不可修改的.也就是说,对扩展是开放的,而对修改是封闭的. 因此,开放封闭原则主要体现在两个方面: 对扩展开放,意味着有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况. 对修改封闭,意味着类一旦设计完成,就可以独立完成其工作,而不要对类进行任何修改

开放—封闭原则

案例:求职考研两不误.考研失败,工作没准备,这是不行的 开放——封闭原则:是说软件实体(类.模块.函数等等)应该可以扩展,但是不可修改. 两个特征:对应扩展是开放的,对于更改是封闭的. 怎么样的设计才能面对需求的改变却可以保持相对稳定,从而使得系统可以在第一个版本以后不断推出新的版本?:开放——封闭原则 案例:公司职员迟到:不可改变的是业绩成效,可改变的是上班的时间 无论模块是多么封闭,都会存在一些无法对之封闭的变化.既然不可能完全封闭,设计人员必须对于他设计的模块应该对哪块变化封闭做出选择.必

Charpter04 开放-封闭原则

开放封闭原则简介 开放-封闭原则,是说软件实体(类.模块.函数等等)应该可以扩展,但是不可修改. 这个原则其实是有两个特征,一个是说,“对于扩展是开放的(Open for extension)”,另一个是说“对于更改是封闭的(Closed for modification)”. 开放封闭原则可以使当需求改变时,可以保持程序的相对稳定,不至于让程序推倒重来,并能使系统可以在第一个版本以后不断的推出新的版本. 无论模块是多么的“封闭”,都会存在一些无法对之封闭的变化,既然不可能完全封闭,设计人员必须

面向对象原则之一 依赖倒置原则

原文:面向对象原则之一 依赖倒置原则 前言 面向对象有人分为五大原则,分别为单一职责原则.开放封闭原则.依赖倒置原则.接口隔离原则.里氏替换原则. 也有人分为六大原则,分别为单一职责原则.开放封闭原则.依赖倒置原则.接口隔离原则.里氏替换原则.迪米特法则. 现在我们来介绍依赖倒置原则 依赖倒置原则 1)概念 a.高层模块不应该依赖于底层模块,两者应该依赖于其抽象. b.抽象不应该依赖具体实现,具体实现应该依赖抽象. 上面2点是依赖倒置原则的概念,也是核心.主要是说模块之间不要依赖具体实现,依赖接

面向对象原则之一 接口隔离原则

原文:面向对象原则之一 接口隔离原则 前言 面向对象有人分为五大原则,分别为单一职责原则.开放封闭原则.依赖倒置原则.接口隔离原则.里氏替换原则. 也有人分为六大原则,分别为单一职责原则.开放封闭原则.依赖倒置原则.接口隔离原则.里氏替换原则.迪米特法则. 现在我们来介绍接口隔离原则 接口隔离原则 1)概念 客户端不应该依赖它不需要的接口.一个类对另一个类的依赖应该建立在最小的接口上. 怎么理解呢?通俗一点就是说接口尽量细分,把不需要的方法尽量写在2个不同的接口上. 假如我有一个接口Interf