软件设计原则
在软件开发中,为了提高软件系统的可维护性和复用性,增加软件的可扩展性和灵活性,作为开发者,我们要根据软件设计的六条原则进行一个开发工作,从而提升软件开发效率、节约软件成本和维护成本。
一、开闭原则
重点理解:对扩展开发,对修改关闭!就是说程序的功能已经无法达到我们的需求了,这个时候不能去修改原有的代码,实现一个新的行为特征,来达到扩展的功能实现。
实现方式:使用接口和抽象类规范我们的开发
抽象的灵活性较好,适应性广,只要抽象的合理,就能保持软件架构的稳定。当软件需要发生变化时,重新派生一个实现类实现即可。
二、里氏代换原则
里氏代换原则是面向对象设计的基本原则之一
原则:任何基类(父类)出现的地方,子类一定可以出现。JavaSE之中的继承就说明了子类可以扩展父类的功能,但不能改变父类原有的功能。简述而言就是继承父类的时候,除了实现扩展功能,尽量不要去重写父类的方法
三、依赖倒换原则
抽象不依赖于具象,具象应该依赖于抽象。简单的说就是要求对抽象的东西编程,不要对具象实现进行编程,这有利于降低与客户之间的耦合
案例:
现要组装一台电脑,需要配件cpu,硬盘,内存条。只有这些配置都有了,计算机才能正常的运行。选择cpu有很多选择,如Intel,AMD等,硬盘可以选择希捷,西数等,内存条可以选择金士顿,海盗船等。
代码实例:
希捷硬盘类
public class XiJieHardDisk implements HardDisk {
public void save(String data) {
System.out.println("使用希捷硬盘存储数据" + data);
}
public String get() {
System.out.println("使用希捷希捷硬盘取数据");
return "数据";
}
}
Intel处理器
public class IntelCpu implements Cpu {
public void run() {
System.out.println("使用Intel处理器");
}
}
金士顿内存条
public class KingstonMemory implements Memory {
public void save() {
System.out.println("使用金士顿作为内存条");
}
}
电脑类
public class Computer {
private XiJieHardDisk hardDisk; //希捷硬盘
private IntelCpu cpu;//CPU
private KingstonMemory memory; //内存条
public IntelCpu getCpu() {
return cpu;
}
public void setCpu(IntelCpu cpu) {
this.cpu = cpu;
}
public KingstonMemory getMemory() {
return memory;
}
public void setMemory(KingstonMemory memory) {
this.memory = memory;
}
public XiJieHardDisk getHardDisk() {
return hardDisk;
}
public void setHardDisk(XiJieHardDisk hardDisk) {
this.hardDisk = hardDisk;
}
public void run() {
System.out.println("计算机开始工作....");
cpu.run();
memory.save();
String data = hardDisk.get();
System.out.println("从硬盘中获取的数据为:" + data);
}
}
测试类
public class TestComputer {
public static void main(String[] args) {
Computer computer = new Computer();
computer.setHardDisk(new XiJieHardDisk());
computer.setCpu(new IntelCpu());
computer.setMemory(new KingstonMemory());
computer.run();
}
}
在组装电脑的时候,我们肯定是会根据自己的喜爱选择不同的品牌CPU、内存条等。
根据依赖倒换原则进行改进!!
代码需要修改computer类,让computer类依赖接口去编程,而不是依赖其中的每个实现类
public class Computer {
private HardDisk hardDisk;
private Cpu cpu;
private Memory memory;
public HardDisk getHardDisk() {
return hardDisk;
}
public void setHardDisk(HardDisk hardDisk) {
this.hardDisk = hardDisk;
}
public Cpu getCpu() {
return cpu;
}
public void setCpu(Cpu cpu) {
this.cpu = cpu;
}
public Memory getMemory() {
return memory;
}
public void setMemory(Memory memory) {
this.memory = memory;
}
public void run() {
System.out.println("计算机工作");
}
}
四、接口隔离原则
客户端不应该被迫依赖于它不使用的方法;一个类对另一个类的依赖应该建立在最小的接口上。
这个概念就很容易了,就比如我们现在要去咖啡店买咖啡。肯定是会选择自己喜欢喝的咖啡类型。如果这个咖啡店说你要是想买这个你喜欢喝的咖啡还必须买另一种咖啡,这个时候肯定你就不乐意了。
所以JDK8就提供了这种新特性,接口当中的默认方法,你也可以理解成实例方法。这也就意味着你去实现该接口的时候不需要去实现该接口下的默认方法。
案例:买咖啡
咖啡接口 提供了两种不同类型的咖啡
package com.tyf.principles.demo2;
public interface Coffee {
void cappuccino(); //卡布奇诺
public default void caffeLatte(){
}; //拿铁咖啡
}
实现类
package com.tyf.principles.demo2;
public class CoffeeImpl implements Coffee{
//不需要强制实现默认方法
@Override
public void cappuccino() {
}
}
五、迪米特原则
迪米特原则又叫最少知道原则。
只和你的直接朋友交谈,不跟“陌生人”说话(Talk only to your immediate friends and not to strangers)。
其含义是:如果两个软件实体无须直接通信,那么就不应当发生直接的相互调用,可以通过第三方转发该调用。其目的是降低类之间的耦合度,提高模块的相对独立性。
迪米特法则中的“朋友”是指:当前对象本身、当前对象的成员对象、当前对象所创建的对象、当前对象的方法参数等,这些对象同当前对象存在关联、聚合或组合关系,可以直接访问这些对象的方法。
六、合成复用原则
聚合关系:关联关系的一种,是强关联关系,是整体和部分之间的关系。
组合关系:表示类之间的整体与部分的关系,但它是一种更强烈的聚合关系。
合成复用原则是指:尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。
通常类的复用分为继承复用和合成复用两种。