SOLID 设计原则
SOLID 原则基本概念:
程序设计领域, SOLID (单一功能、开闭原则、里氏替换、接口隔离以及依赖反转)是由罗伯特·C·马丁在21世纪早期 引入的记忆术首字母缩略字,指代了面向对象编程和面向对象设计的五个基本原则。当这些原则被一起应用时,它们使得一个程序员开发一个容易进行软件维护和扩展的系统变得更加可能SOLID被典型的应用在测试驱动开发上,并且是敏捷开发以及自适应软件开发的基本原则的重要组成部分。
[S] Single Responsibility Principle (单一功能原则)
单一功能原则 :单一功能原则 认为对象应该仅具有一种单一功能的概念。
换句话说就是让一个类只做一种类型责任,当这个类需要承担其他类型的责任的时候,就需要分解这个类。在所有的SOLID原则中,这是大多数开发人员感到最能完全理解的一条。严格来说,这也可能是违反最频繁的一条原则了。单一责任原则可以看作是低耦合、高内聚在面向对象原则上的引申,将责任定义为引起变化的原因,以提高内聚性来减少引起变化的原因。责任过多,可能引起它变化的原因就越多,这将导致责任依赖,相互之间就产生影响,从而极大的损伤其内聚性和耦合度。单一责任,通常意味着单一的功能,因此不要为一个模块实 现过多的功能点,以保证实体只有一个引起它变化的原因。
namespace SOLID
{
public class Users
{
/// <summary>
/// 支付
/// </summary>
public void Pay(){} /// <summary>
/// 数据库操作
/// </summary>
public void DataAccess(){} /// <summary>
/// 日志操作
/// </summary>
public void Logger(){}
}
}
在这个用户类中有这三个功能:1.支付逻辑,2数据库逻辑,3.日志操作。如果将这三个功能结合在一个类中,可能会出现修改部分代码时会破坏其他的部分。多个功能也使这个用户类难以理解,降低了内聚性。所以最好就是将这个类分离为三个分离的类,每个类仅仅有一个功能。
namespace SOLID
{
/// <summary>
/// 数据库操作
/// </summary>
class DataAccess { }
/// <summary>
/// 日志
/// </summary>
class Logger { }
/// <summary>
/// 支付
/// </summary>
class Pay { }
}
[o] Open Close Principle (开闭原则)
开闭原则(ocp) 认为“软件体应该是对于扩展开放的,但是对于修改封闭的”的概念。
软件实体应该是可扩展,而不可修改的。也就是说,对扩展是开放的,而对修改是封闭的。这个原则是诸多面向对象编程原则中最抽象、最难理解的一个。
对扩展开放,意味着有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况。
对修改封闭,意味着类一旦设计完成,就可以独立完成其工作,而不要对类进行任何修改。
可以使用变化和不变来说明:封装不变部分,开放变化部分,一般使用接口继承实现方式来实现“开放”应对变化,说大白话就是:你不是要变化吗?,那么我就让你继承实现一个对象,用一个接口来抽象你的职责,你变化越多,继承实现的子类就越多。
abstract class DataAccess
{
public abstract void OpenConnection();
public abstract void CloseConnection();
public abstract void ExecuteCommand();
} /// <summary>
/// SQL
/// </summary>
class SqlDataAccess : DataAccess
{
/// <summary>
/// 打开SQL数据库
/// </summary>
public override void OpenConnection(){}
/// <summary>
/// 关闭Sql数据连接
/// </summary>
public override void CloseConnection(){}
/// <summary>
/// 执行Sql数据命令
/// </summary>
public override void ExecuteCommand(){}
} /// <summary>
/// ORACLE
/// </summary>
class OracleDataAccess : DataAccess
{
/// <summary>
/// 打开Oracle数据连接
/// </summary>
public override void OpenConnection(){}
/// <summary>
/// 关闭Oracle数据连接
/// </summary>
public override void CloseConnection(){}
/// <summary>
/// 执行Oracle数据命令
/// </summary>
public override void ExecuteCommand(){}
}
[L] Liskov Substitution Principle(里氏替换原则)
里氏替换原则 :里氏替换原则 认为“程序中的对象应该是可以在不改变程序正确性的前提下被它的子类所替换的”的概念。
软件工程大师Robert C. Martin把里氏替换原则最终简化为一句话:“Subtypes must be substitutable for their base types”。也就是,子类必须能够替换成它们的基类。即:子类应该可以替换任何基类能够出现的地方,并且经过替换以后,代码还能正常工作。另外,不应该 在代码中出现if/else之类对子类类型进行判断的条件。里氏替换原则LSP是使代码符合开闭原则的一个重要保证。正是由于子类型的可替换性才使得父类 型的模块在无需修改的情况下就可以扩展。在很多情况下,在设计初期我们类之间的关系不是很明确,LSP则给了我们一个判断和设计类之间关系的基准:需不需 要继承,以及怎样设计继承关系。
当一个子类的实例应该能够替换任何其超类的实例时,它们之间才具有is-A关系。继承对于OCP,就相当于多态性对于里氏替换原则。子类可以代替基类,客户使用基类,他们不需要知道派生类所做的事情。这是一个针对行为职责可替代的原则,如果S是T的子类型,那么S对象就应该在不改变任何抽象属性情况下替换所有T对象。
class Rectangle
{
protected int width = ;
protected int height = ;
public virtual void SetWidth(int width)
{
this.width = width;
}
public virtual void SetHeight(int height)
{
this.height = height;
}
public virtual int GetArea()
{
return this.width * this.height;
}
}
class Square : Rectangle
{
public override void SetHeight(int height)
{
this.height = height;
this.width = height;
}
public override void SetWidth(int width)
{
this.height = width;
this.width = width;
}
}
[I] Interface Segregation Principle(接口隔离原则)
接口隔离原则 :接口隔离原则 认为“多个特定客户端接口要好于一个宽泛用途的接口”的概念。
不能强迫用户去依赖那些他们不使用的接口。换句话说,使用多个专门的接口比使用单一的总接口总要好。注意:在代码中应用ISP并不一定意味着服务就是绝对安全的。仍然需要采用良好的编码实践,以确保正确的验证与授权。
这个原则起源于施乐公司,他们需要建立了一个新的打印机系统,可以执行诸如装订的印刷品一套,传真多种任务。此系统软件创建从底层开始编制,并实现了这些 任务功能,但是不断增长的软件功能却使软件本身越来越难适应变化和维护。每一次改变,即使是最小的变化,有人可能需要近一个小时的重新编译和重新部署。这 是几乎不可能再继续发展,所以他们聘请罗伯特Robert帮助他们。他们首先设计了一个主要类Job,几乎能够用于实现所有任务功能。只要调用Job类的 一个方法就可以实现一个功能,Job类就变动非常大,是一个胖模型啊,对于客户端如果只需要一个打印功能,但是其他无关打印的方法功能也和其耦合,ISP 原则建议在客户端和Job类之间增加一个接口层,对于不同功能有不同接口,比如打印功能就是Print接口,然后将大的Job类切分为继承不同接口的子 类,这样有一个Print Job类,等等。
interface IDataAccess
{
void OpenConnection();
void CloseConnection();
} interface ISqlDataAccess : IDataAccess
{
void ExecuteSqlCommand();
}
interface IOracleDataAccess : IDataAccess
{
void ExecuteOracleCommand();
}
class SqlDataAccess : ISqlDataAccess
{
/// <summary>
/// 执行Sql数据命令
/// </summary>
public void ExecuteSqlCommand(){} /// <summary>
/// 打开Sql数据连接
/// </summary>
public void OpenConnection(){} /// <summary>
/// 关闭Sql数据连接
/// </summary>
public void CloseConnection(){}
}
class OracleDataAccess : IOracleDataAccess
{
/// <summary>
/// 执行Oracle数据命令
/// </summary>
public void ExecuteOracleCommand(){} /// <summary>
/// 打开Oracle数据连接
/// </summary>
public void OpenConnection(){} /// <summary>
/// 关闭Oracle数据连接
/// </summary>
public void CloseConnection(){}
}
[D] Dependency Inversion Principle(依赖反转原则)
依赖反转原则: 依赖反转原则 认为一个方法应该遵从“依赖于抽象而不是一个实例” 的概念。依赖注入是该原则的一种实现方式。
依赖倒置原则(Dependency Inversion Principle,DIP)规定:代码应当取决于抽象概念,而不是具体实现。
高层模块不应该依赖于低层模块,二者都应该依赖于抽象
抽象不应该依赖于细节,细节应该依赖于抽象
类可能依赖于其他类来执行其工作。但是,它们不应当依赖于该类的特定具体实现,而应当是它的抽象。这个原则实在是太重要了,社会的分工化,标准化都 是这个设计原则的体现。显然,这一概念会大大提高系统的灵活性。如果类只关心它们用于支持特定契约而不是特定类型的组件,就可以快速而轻松地修改这些低级 服务的功能,同时最大限度地降低对系统其余部分的影响。
interface IBankAccount
{
long BankNumber { get; set; } // 卡号
decimal Balance { get; set; } // 余额
}
// 转账人
interface ITransferSource : IBankAccount
{
void CutPayment(decimal value);
}
// 收款人
interface ITransferDestination : IBankAccount
{
void AddMoney(decimal value);
}
class BankAccout : IBankAccount, ITransferSource, ITransferDestination
{
public long BankNumber { get; set; }
public decimal Balance { get; set; }
public void CutPayment(decimal value)
{
Balance -= value;
}
public void AddMoney(decimal value)
{
Balance += value;
}
}
class TransferAmount
{
public decimal Amount { get; set; }
public void Transfer(ITransferSource source, ITransferDestination dest)
{
source.CutPayment(Amount);
dest.AddMoney(Amount);
}
}
参考于:
http://www.cnblogs.com/Ax0ne/p/3619481.html
http://www.cnblogs.com/shanyou/archive/2009/09/21/1570716.html
SOLID 设计原则的更多相关文章
- SOLID 设计原则 In C# 代码实现
[S] Single Responsibility Principle (单一职责原则) 认为一个对象应该仅只有一个单一的职责 namespace SingleResponsibilityPrinci ...
- 适用于Java开发人员的SOLID设计原则简介
看看这篇针对Java开发人员的SOLID设计原则简介.抽丝剥茧,细说架构那些事——[优锐课] 当你刚接触软件工程时,这些原理和设计模式不容易理解或习惯.我们都遇到了问题,很难理解SOLID + DP的 ...
- SOLID设计原则
SOLID设计原则 Single Responsibility Principle单一职责原则 单一职责原则(SRP)表明一个类有且只有一个职责. 一个类就像容器一样,它能添加任意数量的属性.方法等. ...
- 工作那么久,才知道的 SOLID 设计原则
认识 SOLID 原则 无论是软件系统设计,还是代码实现,遵循有效和明确的设计原则,都利于系统软件灵活可靠,安全快速的落地,更重要的是能灵活地应对需求,简化系统扩展和维护,避免无效的加班.本文主要讨论 ...
- 面向对象SOLID设计原则之Open-Closed原则
首先,我们看下开放-封闭原则(Open-Closed Principle,简称OCP)的概念: 是指软件实体(类.模块.函数等)应该可以扩展,但是不可修改. 任何新功能(functionality)应 ...
- PHP的SOLID设计原则
SOLID Design Principles, 这是一个比设计模式更高级别的概念, 以构建良好代码为目标,真正掌握了就是大师级别了. 我~~~仅知晓~ /*SOLID Design Principl ...
- SOLID架构设计原则
最近通读了<架构整洁之道>,受益匪浅,遂摘选出设计原则部分,与大家分享,希望大家能从中获益. 以下为书中第3部分 设计原则的原文. 设计原则概述 通常来说,要想构建-个好的软件系统,应该从 ...
- 经典设计原则 - SOLID
SOLID 设计原则包含以下 5 种原则: 单一职责原则(Single Responsibility Principle, SRP) 开闭原则(Open Closed Principle, OCP) ...
- Java程序员应该了解的10个面向对象设计原则
面向对象设计原则: 是OOPS(Object-Oriented Programming System,面向对象的程序设计系统)编程的核心,但大多数Java程序员追逐像Singleton.Decorat ...
随机推荐
- Canvas讲解
1.Canvas是什么? 简单地说canvas是画布,可以进行画任何的线.图形.填充等一系列的操作,而且操作的画图就是js, 提供简单的二维矢量绘图. 2.步骤: <canvas id=&quo ...
- Javascript 严格模式详解
转自http://www.ruanyifeng.com/blog/2013/01/javascript_strict_mode.html 一.概述 除了正常运行模式,ECMAscript 5添加了第二 ...
- React Native Android gradle下载慢问题解决
很多人会遇到 初次运行 react-native run android的时候 gradle下载极慢,甚至会失败的问题 如下图 实际上这个问题好解决的 首先 把对应版本的gradle下载到本地任意一个 ...
- 敏捷转型历程 - Sprint3 Planning
我: Tech Leader 团队:团队成员分布在两个城市,我所在的城市包括我有4个成员,另外一个城市包括SM有7个成员.另外由于我们的BA离职了,我暂代IT 的PO 职位.PM和我在一个城市,但他不 ...
- hbase集群安装与部署
1.相关环境 centos7 hadoop2.6.5 zookeeper3.4.9 jdk1.8 hbase1.2.4 本篇文章仅涉及hbase集群的搭建,关于hadoop与zookeeper的相关部 ...
- Linux自动共享USB设备:udev+Samba
一.概述 公司最近要我实现USB设备插入Ubuntu后,自动共享到网络上,能像Windows共享一样(如\\192.168.1.10)访问里面的内容,不需要写入权限.当时听完这需求,我这新人表示惊呆了 ...
- jsp
-----------------
- Forward+ Rendering Framework
近几天啃各种新技术时又一个蛋疼的副产品...额,算是把AMD的Forward+ Sample抄了一遍吧. 其实个人感觉这个AMD大肆宣传的Forward+跟Intel很早之前提的Tiled-Based ...
- JS案例之3——倒计时
利用简单的数字累加循环模拟倒计时的效果,逻辑比较简单.如果大牛们有更好的办法欢迎补充. 这种效果经常用于在规定的时间做某件事.比如在1分钟之后重新发送验证码等. 案例演示: 源代码如下: <!D ...
- HTML5- Canvas入门(五)
今天要介绍的是canvas对图形对象的操作,包括图像.视频绘制,和操作像素对象的方法. 图片/视频的绘制 在canvas中,我们可以通过 drawImage() 的方法来绘制图片或视频文件,其语法为: ...