欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

软件设计的7大原则

程序员文章站 2024-02-10 08:10:28
...

1、开放-封闭原则

         对模块、类、函数扩展开发、对修改关闭。强调使用抽象构建框架,用实现扩展细节,从而提高软件系统的复用性和扩展性。开闭原则是面向对象设计中最基础的设计原则,指导我们如何构建稳定灵活的系统。

例如:在版本更新的时候,尽可能的不修改已有源代码,通过新增类来扩展功能。

/**
 * 支付
 */
public interface Payment {

    /**
     * 扣款
     * @param amount 金额
     * @return
     */
    String pay(int amount);
}

public class Alipay implements Payment{

    public String pay(int amount) {

        return "扣款"+amount+"元";
    }
}

public class DiscountAlipay extends Alipay{

    /**
     * 打折优惠
     * @param totalPrice
     * @param discountAmount
     * @return
     */
    public String discount(int totalPrice, int discountAmount){

        return pay(totalPrice - discountAmount);

    }
}

2、依赖倒置原则

设计代码结构时,高层模块不应该依赖底层的模块,二者应该依赖其抽象,让细节依赖抽象。通过依赖倒置原则,可以减少类与类之间的耦合性,提高系统的稳定性,可读性和可维护性,降低修改给程序带来的风险。

例如:用户扫描二维码后可以选择多种支付方式

public class WechatPay implements Payment{

    public String pay(int amount) {
        return null;
    }
}

public class User {

    private String name;

    private Payment payment;

    public void setName(String name) {
        this.name = name;
    }

    public void setPayment(Payment payment) {
        this.payment = payment;
    }

    public String pay(int amount){
       return payment.pay(amount);
    }
}

public class AppTest 
{
    public static void main(String[] args) {

        User tom = new User();
        tom.setName("tom");
        tom.setPayment(new Alipay());
        tom.pay(100);

        User jack= new User();
        jack.setName("jack");
        jack.setPayment(new WechatPay ());
        tom.pay(200);

    }
}

3、单一职责原则

指一个类或一个方法,只负责一个职责,避免修改其中一个类或一个方法逻辑,造成另外一个类或方法功能故障。

职责划分可以对功能解耦,降低系统复杂度,提高维护性性、可读性。

例如:上面的例子中,Alipay和WechatPay,支付的实现细节不同,对支付方式的不同,划分了不同的类。

 

4、接口隔离原则

使用多个专门的总接口,而不使用一个总的接口,客户端不应该依赖不需要的接口。设计接口是应该遵循的几个点:

(1)类一对一的依赖应该建立在最小的接口之上

(2)建立单一接口,不要建立臃肿的接口

(3)尽量细化接口,接口中的方法数量要适度。

接口隔离原则复合高类聚,低耦合的设计思想,类具有良好的可读性、可扩展性、可维护性。接口设计的时候要多花时间思考业务模型,对可能发生的变更提前预判,所以抽象对模型的理解非常重要。

public interface Animal {

    void eat();

    void fly();

    void swing();
}

public class Bird implements Animal {
    public void eat() {
        System.out.println("喜欢吃虫子!");
    }

    public void fly() {
        System.out.println("鹰击长空");
    }

    public void swing() {

    }
}

public class Dog implements Animal {
    public void eat() {
        System.out.println("喜欢磕骨头");
    }

    public void fly() {

    }

    public void swing() {
        System.out.println("擅长游泳");
    }
}

public class Cat implements Animal{
    public void eat() {
        System.out.println("喜欢吃鱼");
    }

    public void fly() {

    }

    public void swing() {

    }
}

每个类都有空着的方法,dog和cat显然是不要fly方法的,通过设计不同功能的接口进行改糙,如下:

public interface Flyable {
    void fly();
}

public interface Eatable {
    void eat();
}

public interface Swimming {
    void swing();
}

public class Bird implements Flyable,Eatable {
    public void eat() {
        System.out.println("喜欢吃虫子!");
    }

    public void fly() {
        System.out.println("鹰击长空");
    }
}

public class Dog implements Eatable,Swimming {
    public void eat() {
        System.out.println("喜欢磕骨头");
    }

    public void swing() {
        System.out.println("擅长游泳");
    }
}

public class Cat implements Eatable{
    public void eat() {
        System.out.println("喜欢吃鱼");
    }
}

5、迪米特法则

一个类对其他类应该有最少的了解,又叫最少知道原则,降低累于类之间的耦合性。迪米特法则强调只和朋友交流,不和陌生人说话,类的成员变量、方法的输入输出参数称为朋友,方法体内部的类不属于朋友。

例如:Boss需要季度,年度报表,只需要找到数据部门的主管,主管让下面擅长做报表的员工制作报表,然后主管反馈报表给Boss,Boss不需要自己去了解报表是怎么做的。

 

6、里式替换原则

代码编写中适用于父类的地方,那么一定适用子类。所以引用父类方法的地方必须可以透明底适用子类,子类对象可以替换父类对象,而程序逻辑不变。

引申意思:子类可以扩展父类的功能,但不能改变父类原有功能。

(1)子类可以实现父类的抽象方法,不能覆盖父类的非抽象方法

(2)子类可以增加自己特有的方法

(3)当子类重载父类的方法时,方法的前置条件(方法输入参数)比父类更宽松

(4)子类实现父类方法时,方法的后置添加(方法输出值)比父类更严格或相等。

(3)和(4)指方法的的开发程度,父类是protected,子类至少应该是protectd,宽松就是public; 参数如果是String,那么子类实现和重载的方法至少应该是String,宽松是Object;返回值父类是String,严格就是String的子类,相等就是String。

里式替换的有点:

(1)约束继承泛滥,开闭原则的一种体现

(2)增强程序的健壮性,同时变更做的非常好的兼容性,提高程序维护性,扩展性

 

7、合成复用原则

尽量使用对象组合、聚合,而不是继承达到软件复用的目的。可以降低类与类之间的耦合度,让程序更加灵活。

继承叫做白箱复用,父类把所有的细节暴露给子类。

组合/聚合叫做黑箱复用,对类以外的对象无法获取到实现细节。

例如:以Connection连接为例

public interface Connection {
}

public class DBConnection implements Connection {
}

public class HttpConnection implements Connection{
}

public class ProductServiceImpl {
    
    private Connection connection;

}

service最开始功能只有从数据库查询时,现在需要使用http连接从第三方查询是,增加HttpConnection的对象持有,就可以实现功能的扩展,而不是使用继承。

 

总结:

设计原则是学习设计模式的基础,实际开发过程中不一定要求所有的代码都遵循设计规则,考虑到人力、时间、成本、质量等多方面的因素,适当遵循设计原则。