软件架构设计原则

133 阅读4分钟

开闭原则

开闭原则是指一个软件实体(类、模块、函数)应该对扩展开发,对修改关闭,通过扩展类实现修改 例:

1.创建一个课程接口ICourse

public interface ICourse{
    Integer getId();
    String getName();
    Double getPrice();
}

2.创建课程类JavaCource

public class JavaCourse implements ICourcse{
    private Integer id;
    private String name;
    private Double price;
    public JavaCourse(Integer id,String name,Double price){
        this.id=id;
        this.name=name;
        this.price=price;
    }
    public Integer getId(){
        return this.id;
    }
    public String getName(){
        return this.name;
    }
    public Double getPrice(){
        return this.price;
    }
}

3.假设现在要对课程做优惠

public class JavaDiscountCourse extends JavaCourse{
    public JavaDiscountCourse(Integer id,String name,Double price){
        super(id,nane,price);
    }
    
    public Double getOriginPrice(){
        return super.price;
    }
    public Double getPrice(){
        return super.price*0.8;
    } 
    
}

依赖倒置原则

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

1.以Cource课程为例,创建一个类Tom

public class Tom{
    public void studyJavaCourse(){
        System.out.println("Tom 学习Java课程");
    }
    
    public void studyPythonCourse(){
        System.out.println("Tom 学习Python课程");
    }
}

2.调用

public static void main(String[] args){
    Tom tom = new Tom();
    tom.studyJavaCourse();
    tom.studyPythonCourse();
}

随着学习的课程原来越多,从底层到高层都需要修改代码,比如Tom类中要增加studyAIcourse() 方法,高层也要追加调用,系统很不稳定,如何优化?

1.创建课程的抽象接口

 public interface ICourse{
     void study();
 }

2.编写Course课程类

 public class JavaCourse implements ICourse{
     @overwrite
     public void study(){
        System.out.println("Tom 在学习Java课程");
     }
 }
 
 public class PythonCourse implements ICourse{
     @overwrite
     public void study(){
        System.out.println("Tom 在学习Python课程");
     }
 }
 
  public class AICourse implements ICourse{
     @overwrite
     public void study(){
        System.out.println("Tom 在学习AI课程");
     }
 }

3.修改Tom类

public class Tom{
    public void study(ICource course){
        cource.study();
    }
}

4.如何调用

public static void main(String[] args){
    Tom tom = new Tom();
    tom.study(new JavaCourse());
    tom.study(new PythonCourse());
}

单一职责原则

单一原则是指不要存在多于一个导致类变更的原因。假设我们有一个类负责两个职责,一单需求发生变更,修改了其中一个职责的逻辑代码,有可能导致另一个职责的功能发生故障。如何解决呢?两个职责用两个类来实现,进行解耦。

1.创建Course类

public class Course{
    public void study(String courseName){
        if("直播课".equals(courseName)){
            System.out.println(courseName + "不能快进");
        }else{
            System.out.println(courseName + "可以反复回看"); 
        }
    }
}

2.调用代码

public static void main(String[] args){
    Course course = new Course();
    course.study("直播课");
    course.study("录播课");
}

代码Course类承担了两种处理逻辑。假设现在要对课程进行加密,直播课程和录播课程加密逻辑不一样,必须修改代码,而修改代码的逻辑会相互影响,需要对职责进行解耦,如何修改?

1.分别创建两个类LiveCourse和ReplayCourse

public class LiveCourse{
    public  void  study(String courseName){
        System.out.println(courseName+"不能快进看");
    }
}

public class ReplayCourse{
    public  void  study(String courseName){
        System.out.println(courseName+"可以反复回看");
    }
}

业务继续发展,课程要做权限。没有付费的学员可以获取课程的基本信息,已经付费的学员可以获得视频流,及学习权限。

public interface ICourse{
    String getCourseName();
    byte[] getCourseVideo()
    
    void studyCourse()
    void refundCourse()
}

接口隔离原则

接口隔离原则是指用多个专门的接口,而不使用单一的总接口,客户端不应该依赖他不需要的接口。这个原则指导我们在设计接口是应当注意一下几点: (1)一个类对另外一个类的依赖应该建立在最小的接口之上 (2)建立单一接口,不要建立庞大臃肿的接口 (3)尽量细化接口,接口中的方法尽量少

public interface IAnimal{
    void eat();
    void fly();
    void swim();
}

修改后

public interface IEatAnimal{
    void eat();
}

public interface IFlyAnimal{
    void fly();
}

public interface ISwimAnimal{
    void swim();
}

使用

public class Dog implements ISwimAnimal,IEatAnimal{
    @overwride
    public void eat(){}
    @Override
    public void swim(){}
}

迪米特原则

迪米特原则是指一个对象应该对其他对象保持最小的了解,又叫最少知道原则,尽量降低类与类之间的耦合度,迪米特原则主要强调:之和朋友交流,不和陌生人说话。

反例:

public class TeamLeader{
    public doid checkNumberOfcourses(List<Course> courseList){
        System.out.println("目前已发布课程的数量数量是:"courseList.size());
    }
}

public class Boss{
    public doid commandCheckNumber(TeamLeader teamLeader){
        List<Course>  courseList = New ArrayList<>();
        ...
        teamLeader.checkNumberOfcourses(courseList);
    }
}

修改后

public class TeamLeader{
    public doid checkNumberOfcourses(){
        List<Course>  courseList = New ArrayList<>();
        ...
        System.out.println("目前已发布课程的数量数量是:"courseList.size());
    }
}

public class Boss{
    public doid commandCheckNumber(TeamLeader teamLeader){
        teamLeader.checkNumberOfcourses();
    }
}

里是替换原则

里是替换原则是指如果对每一个类型为T1的对象O1,类型为T2的对象O2,使得T1定义的所有程序P在所有对象O1都替换成O2时,程序P的行为没有发生变化,那么类型T2是类型T1的子类型 子类可以扩展父类的功能,但是不能修改父类的功能

合成复用原则

是指尽量使用对象组合(has-a)/聚合(contains-a)而不是继承关系达到软件复用的目的

反例:

public class DBConnection{
    public String getConnection(){
        return "MySql 数据库连接"
    }
}

public class ProductDao{
    private DBConnection dbconnection;
    public void setDbConnection(DBConnection dbConnection){
        this.dbConnection=dbConnection;
    }
    
    public void addProduct(){
        String conn = dbconnection.getConnection();
        System.out.println("使用"+conn+"增加产品");
    }
}

修改

public abstract class DBConnection{
    public abstract String getConnection();
}

public class MySQLConnection extends DBConnection{
    @override
    public String getConnection(){
        return "mysql 数据库连接";
    }
}