软件设计原则
概述:
软件开发过程中,为了提高系统的可维护性和可复用性,增加软件的可扩展性和灵活性,程序员应该尽量遵循7大原则来开发程序,从而提高软件开发效率,节约软件开发成本和维护成本。
7大设计原则,侧重点不同
开闭原则是总纲,对扩展开放,对修改关闭。
里氏替换原则,不要破坏类的继承。
依赖倒置原则,面向接口编程。
单一职责,类要单一。
接口隔离原则,告诉我们设计接口的时候要精简单一。
迪米特法则,降低代码耦合度。
合成复用法则,优先使用组合或者聚合关系复用,少用继承关系复用
开闭原则
开闭原则的含义是:当应用的需求改变时,在不修改软件实体的源代码或者二进制代码的前提下,可以扩展模块的功能,使其满足新的需求。
l 对软件测试的影响软件遵守开闭原则的话,软件测试时只需要对扩展的代码进行测试就可以了,因为原有的测试代码仍然能够正常运行。
l 可以提高代码的可复用性粒度越小,被复用的可能性就越大;在面向对象的程序设计中,根据原子和抽象编程可以提高代码的可复用性。
l 可以提高软件的可维护性遵守开闭原则的软件,其稳定性高和延续性强,从而易于扩展和维护。
栗子:
/**
* 抽象绘制图形类
*/
abstract class Shape {
abstract void draw();
}
public class Circle extends Shape {
void draw() {
System.out.println("绘制圆形");
}
}
public class Rectangle extends Shape{
void draw() {
System.out.println("绘制三角形");
}
}
public class GraphicEditor {
public void drawShape(Shape shape) {
shape.draw();
}
}
测试类:
public class TestMain {
public static void main(String[] args) {
GraphicEditor graphicEditor = new GraphicEditor();
graphicEditor.drawShape(new Rectangle());
graphicEditor.drawShape(new Circle());
//方便扩展 对修改关闭 对扩展开放
}
}
业务抽象,例多平台发送消息(微信,QQ,邮件,新浪邮箱,阿里短信平台...)
里氏替换原则
l 里氏替换原则是实现开闭原则的重要方式之一。
l 它克服了继承中重写父类造成的可复用性变差的缺点。
l 它是动作正确性的保证。即类的扩展不会给已有的系统引入新的错误,降低了代码出错的可能性。
子类可以扩展父类的功能,但是不能改变父类原有的功能。
问题描述:
public class A {
public int func1(int a, int b) {
return a - b;
}
}
class B extends A {
@Override
public int func1(int a, int b) {
return a + b;
}
public int func2(int a, int b) {
return func1(a, b) + 100;
}
}
class C {
public static void main(String[] args) {
B b = new B();
System.out.println("100-50=" + b.func1(100, 50));
System.out.println("100-80=" + b.func1(100, 80));
System.out.println("100+20+100=" + b.func2(100, 20));
}
}
输出结果:
100-50=150
100-80=180
100+20+100=220
里氏替换原则是应该避免的原则。增加代码问题风险。
依赖倒置原则
l 依赖倒置原则的主要作用如下。
l 依赖倒置原则可以降低类间的耦合性。
l 依赖倒置原则可以提高系统的稳定性。
l 依赖倒置原则可以减少并行开发引起的风险。
l 依赖倒置原则可以提高代码的可读性和可维护性。
问题设计示例:
public class Driver {
public void driver(Ben ben) {
ben.run();
}
}
class Ben {
public void run() {
System.out.println("奔驰汽车");
}
}
class TestMain {
public static void main(String[] args) {
Driver driver = new Driver();
driver.driver(new Ben());
}
}
设想一下如果这时多了奥迪,丰田,大众,红旗... 代码之间耦合度过高 违反依赖倒置原则
这里不应该是 一个司机依赖车。反过来会更好 车依赖于司机。
public interface IDriver {
void driver(ICar iCar);
}
public interface ICar {
void run();
}
public class Driver implements IDriver {
public void driver(ICar iCar) {
iCar.run();
}
}
public class Car implements ICar {
public void run() {
System.out.println("汽车运行");
}
}
public class TestMain
{
public static void main(String[] args) {
Driver driver = new Driver();
driver.driver(new Car());
}
}
深入理解
依赖倒置原则的本质就是通过抽象(抽象类或接口)使各个类或模块实现彼此独立,不互相影响,实现模块间的松耦合。在项目中使用这个规则需要以下原则;
每个类尽量都要有接口或抽象类,或者抽象类和接口都有: 依赖倒置原则的基本要求,有抽象才能依赖倒置
变量的表面类型尽量是接口或者抽象类
任何类都不应该从具体类派生
尽量不要重写基类已经写好的方法(里式替换原则)
结合里式替换原则来使用: 结合里式替换原则和依赖倒置原则我们可以得出一个通俗的规则,接口负责定义public属性和方法,并且声明与其他对象的依赖关系,抽象类负责公共构造部分的实现,实现类准确的实现业务逻辑,同时在适当的时候对父类进行细化。
一句话:依赖倒置原则的核心就是面向抽象(抽象类或者接口)编程
单一职责原则
l 单一职责原则的核心就是控制类的粒度大小、将对象解耦、提高其内聚性。如果遵循单一职责原则将有以下优点。
l 降低类的复杂度。一个类只负责一项职责,其逻辑肯定要比负责多项职责简单得多。
l 提高类的可读性。复杂性降低,自然其可读性会提高。
l 提高系统的可维护性。可读性提高,那自然更容易维护了。
l 变更引起的风险降低。变更是必然的,如果单一职责原则遵守得好,当修改一个功能时,可以显著降低对其他功能的影响。
l 注意:单一职责同样也适用于方法。一个方法应该尽可能做好一件事情。如果一个方法处理的事情太多,其颗粒度会变得很粗,不利于重用。
public interface IPhone{
//拨通电话
public void dial(String phoneNumber);
//通话
public void chat(Object o);
//挂断电话
public void hangup();
}
相对于类或者方法:对象制作一件事。
接口隔离原则
l 将臃肿庞大的接口分解为多个粒度小的接口,可以预防外来变更的扩散,提高系统的灵活性和可维护性。
l 接口隔离提高了系统的内聚性,减少了对外交互,降低了系统的耦合性。
l 如果接口的粒度大小定义合理,能够保证系统的稳定性;但是,如果定义过小,则会造成接口数量过多,使设计复杂化;如果定义太大,灵活性降低,无法提供定制服务,给整体项目带来无法预料的风险。
l 使用多个专门的接口还能够体现对象的层次,因为可以通过接口的继承,实现对总接口的定义。
l 能减少项目工程中的代码冗余。过大的大接口里面通常放置许多不用的方法,当实现这个接口的时候,被迫设计冗余的代码。
接口细分,例如一个水果接口,不要把所有水果全部放到一个接口。
分为:生产水果 销售水果 邮寄水果 榨汁水果接口...
迪米特法则
l 迪米特法则要求限制软件实体之间通信的宽度和深度,正确使用迪米特法则将有以下两个优点。
l 降低了类之间的耦合度,提高了模块的相对独立性。
l 由于亲合度降低,从而提高了类的可复用率和系统的扩展性。
合成复用法则
通常类的复用分为继承复用和合成复用两种,继承复用虽然有简单和易实现的优点,但它也存在以下缺点。
l 继承复用破坏了类的封装性。因为继承会将父类的实现细节暴露给子类,父类对子类是透明的,所以这种复用又称为“白箱”复用。
l 子类与父类的耦合度高。父类的实现的任何改变都会导致子类的实现发生变化,这不利于类的扩展与维护。
l 它限制了复用的灵活性。从父类继承而来的实现是静态的,在编译时已经定义,所以在运行时不可能发生变化。
采用组合或聚合复用时,可以将已有对象纳入新对象中,使之成为新对象的一部分,新对象可以调用已有对象的功能,它有以下优点。
l 它维持了类的封装性。因为成分对象的内部细节是新对象看不见的,所以这种复用又称为“黑箱”复用。
l 新旧类之间的耦合度低。这种复用所需的依赖较少,新对象存取成分对象的唯一方法是通过成分对象的接口。
l 复用的灵活性高。这种复用可以在运行时动态进行,新对象可以动态地引用与成分对象类型相同的对象。
标签:六大,原则,void,复用,接口,class,软件,public From: https://www.cnblogs.com/li-xiaotian/p/16602498.html