设计模式之七大原则

发布时间 2023-12-03 21:09:14作者: 突破铁皮

单一职责原则

类的职责要单一,不能将太多的职责放在一个类中。

请看代码示例:

未采用单一职责原则

package com.std.www.designPattern.principle;

class Student{
    public void getDBConnection(){
        System.out.println("连接到数据库");
    }
    public void addStudent(){
        System.out.println("增加了一名学生");
    }
    public void removeStudent(){
        System.out.println("移除了一名学生");
    }
    public void closeDBConnection(){
        System.out.println("关闭连接");
    }
}
class Teacher{
    public void getDBConnection(){
        System.out.println("连接到数据库");
    }
    public void addTeacher(){
        System.out.println("增加了一名老师");
    }
    public void removeTeacher(){
        System.out.println("移除了一名老师");
    }
    public void closeDBConnection(){
        System.out.println("关闭连接");
    }
}

public class Client {
    public static void main(String[] args) {
        Student student=new Student();
        student.getDBConnection();
        student.addStudent();
        student.removeStudent();
        student.closeDBConnection();
        Teacher teacher=new Teacher();
        teacher.getDBConnection();
        teacher.addTeacher();
        teacher.removeTeacher();
        teacher.closeDBConnection();
    }
}

采用单一职责原则

package com.std.www.designPattern.principle;

class Student{
    private DBConnection dbConnection;

    public Student(DBConnection dbConnection) {
        this.dbConnection = dbConnection;
    }

    public void addStudent(){
        dbConnection.getDBConnection();
        System.out.println("增加了一名学生");
        dbConnection.closeDBConnection();
    }
    public void removeStudent(){
        dbConnection.getDBConnection();
        System.out.println("移除了一名学生");
        dbConnection.closeDBConnection();
    }
}
class Teacher{
    private DBConnection dbConnection;

    public Teacher(DBConnection dbConnection) {
        this.dbConnection = dbConnection;
    }

    public void addTeacher(){
        dbConnection.getDBConnection();
        System.out.println("增加了一名老师");
        dbConnection.closeDBConnection();
    }
    public void removeTeacher(){
        dbConnection.getDBConnection();
        System.out.println("移除了一名老师");
        dbConnection.closeDBConnection();
    }
}
class DBConnection{
    public void getDBConnection(){
        System.out.println("连接到数据库");
    }
    public void closeDBConnection(){
        System.out.println("关闭连接");
    }
}

public class Client {
    public static void main(String[] args) {
        Student student=new Student(new DBConnection());
        student.addStudent();
        student.removeStudent();
        Teacher teacher=new Teacher(new DBConnection());
        teacher.addTeacher();
        teacher.removeTeacher();
    }
}

从这里可以看出,没用采用单一原则下的Student和Teacher中重复写了数据库连接和关闭方法,并且将连接功能和增减功能写在一块,导致了高耦合,而采用之后,数据库连接可以重复利用,降低了的代码的复杂性,提高了内聚性,假设我们新增一个班主任的增删,可以重复调用数据库连接类

接口隔离原则

使用多个专门的接口来取代一个统一的原则。

请看代码示例:

未采用接口分离原则

package com.std.www.designPattern.principle;

interface IObject{
    void addStudent();
    void removeStudent();
    void addTeacher();
    void removeTeacher();
    void getDBConnection();
    void closeDBConnection();
}

class Student implements IObject{
    private DBConnection dbConnection;

    public Student(DBConnection dbConnection) {
        this.dbConnection = dbConnection;
    }

    public void addStudent(){
        dbConnection.getDBConnection();
        System.out.println("增加了一名学生");
        dbConnection.closeDBConnection();
    }
    public void removeStudent(){
        dbConnection.getDBConnection();
        System.out.println("移除了一名学生");
        dbConnection.closeDBConnection();
    }

    @Override
    public void addTeacher() {
        
    }

    @Override
    public void removeTeacher() {

    }

    @Override
    public void getDBConnection() {

    }

    @Override
    public void closeDBConnection() {

    }
}
class Teacher implements IObject{
    private DBConnection dbConnection;

    public Teacher(DBConnection dbConnection) {
        this.dbConnection = dbConnection;
    }

    @Override
    public void addStudent() {
        
    }

    @Override
    public void removeStudent() {

    }

    public void addTeacher(){
        dbConnection.getDBConnection();
        System.out.println("增加了一名老师");
        dbConnection.closeDBConnection();
    }
    public void removeTeacher(){
        dbConnection.getDBConnection();
        System.out.println("移除了一名老师");
        dbConnection.closeDBConnection();
    }

    @Override
    public void getDBConnection() {

    }

    @Override
    public void closeDBConnection() {

    }
}
class DBConnection implements IObject{
    @Override
    public void addStudent() {
        
    }

    @Override
    public void removeStudent() {

    }

    @Override
    public void addTeacher() {

    }

    @Override
    public void removeTeacher() {

    }

    public void getDBConnection(){
        System.out.println("连接到数据库");
    }
    public void closeDBConnection(){
        System.out.println("关闭连接");
    }
}

public class Client {
    public static void main(String[] args) {
        Student student=new Student(new DBConnection());
        student.addStudent();
        student.removeStudent();
        Teacher teacher=new Teacher(new DBConnection());
        teacher.addTeacher();
        teacher.removeTeacher();
    }
}

采用接口分离原则

package com.std.www.designPattern.principle;

interface IStudent{
    void addStudent();
    void removeStudent();
}
interface ITeacher{
    void addTeacher();
    void removeTeacher();
}
interface IDBConnection{
    void getDBConnection();
    void closeDBConnection();
}
class Student implements IStudent{
    private DBConnection dbConnection;

    public Student(DBConnection dbConnection) {
        this.dbConnection = dbConnection;
    }

    public void addStudent(){
        dbConnection.getDBConnection();
        System.out.println("增加了一名学生");
        dbConnection.closeDBConnection();
    }
    public void removeStudent(){
        dbConnection.getDBConnection();
        System.out.println("移除了一名学生");
        dbConnection.closeDBConnection();
    }
}
class Teacher implements ITeacher{
    private DBConnection dbConnection;

    public Teacher(DBConnection dbConnection) {
        this.dbConnection = dbConnection;
    }

    public void addTeacher(){
        dbConnection.getDBConnection();
        System.out.println("增加了一名老师");
        dbConnection.closeDBConnection();
    }
    public void removeTeacher(){
        dbConnection.getDBConnection();
        System.out.println("移除了一名老师");
        dbConnection.closeDBConnection();
    }
}
class DBConnection implements IDBConnection{
    public void getDBConnection(){
        System.out.println("连接到数据库");
    }
    public void closeDBConnection(){
        System.out.println("关闭连接");
    }
}

public class Client {
    public static void main(String[] args) {
        Student student=new Student(new DBConnection());
        student.addStudent();
        student.removeStudent();
        Teacher teacher=new Teacher(new DBConnection());
        teacher.addTeacher();
        teacher.removeTeacher();
    }
}

从上面看出,Student只依赖addStudent和removeStudent方法,同理两外两个类也依赖各自的方法,但我们如果实现第一种接口需要实现所有方法,通过接口隔离原则,我确定每个类的最小依赖接口,使得不同接口之间进行隔离

依赖倒转原则

要针对抽象层编程,而不要针对具体类编程。

请看代码示例:

未采用依赖倒转原则

package com.std.www.designPattern.principle;

interface IStudent{
    void addStudent();
    void removeStudent();
}
interface IDBConnection{
    void getDBConnection();
    void closeDBConnection();
}
class Student implements IStudent {
    private MysqlDBConnection dbConnection;

    public Student(MysqlDBConnection dbConnection) {
        this.dbConnection = dbConnection;
    }

    public void addStudent(){
        dbConnection.getDBConnection();
        System.out.println("增加了一名学生");
        dbConnection.closeDBConnection();
    }
    public void removeStudent(){
        dbConnection.getDBConnection();
        System.out.println("移除了一名学生");
        dbConnection.closeDBConnection();
    }
}
class MysqlDBConnection implements IDBConnection{
    public void getDBConnection(){
        System.out.println("连接到Mysql数据库");
    }
    public void closeDBConnection(){
        System.out.println("关闭Mysql连接");
    }
}
class SqlServerDBConnection implements IDBConnection{
    public void getDBConnection(){
        System.out.println("连接到SqlServer数据库");
    }
    public void closeDBConnection(){
        System.out.println("关闭SqlServer连接");
    }
}

public class Client {
    public static void main(String[] args) {
        Student student=new Student(new MysqlDBConnection());
        student.addStudent();
        student.removeStudent();
    }
}

采用依赖倒转原则

package com.std.www.designPattern.principle;


interface IDBConnection{
    void getDBConnection();
    void closeDBConnection();
}

/**
 * 依赖注入的三种方式
 * */

interface IStudent{
    //接口注入
    void addStudent(IDBConnection idbConnection);
    void removeStudent();
}
class Student implements IStudent{
    private IDBConnection dbConnection;

    //构造注入
    public Student(IDBConnection dbConnection) {
        this.dbConnection = dbConnection;
    }

    //设值注入
    public void setDbConnection(IDBConnection dbConnection) {
        this.dbConnection = dbConnection;
    }

    public void addStudent(IDBConnection idbConnection){
        dbConnection.getDBConnection();
        System.out.println("增加了一名学生");
        dbConnection.closeDBConnection();
    }
    public void removeStudent(){
        dbConnection.getDBConnection();
        System.out.println("移除了一名学生");
        dbConnection.closeDBConnection();
    }
}
class MysqlDBConnection implements IDBConnection{
    public void getDBConnection(){
        System.out.println("连接到Mysql数据库");
    }
    public void closeDBConnection(){
        System.out.println("关闭Mysql连接");
    }
}
class SqlServerDBConnection implements IDBConnection{
    public void getDBConnection(){
        System.out.println("连接到SqlServer数据库");
    }
    public void closeDBConnection(){
        System.out.println("关闭SqlServer连接");
    }
}

public class Client {
    public static void main(String[] args) {
        Student student=new Student(new MysqlDBConnection());
        student.addStudent(new SqlServerDBConnection());
        student.removeStudent();
    }
}

三种注入方式,使得Student根据注入的具体连接类可以连接到不同的数据库,依赖于抽象而非实现

里氏替换原则

在软件系统中,一个可以接受基类对象的地方必然可以接受一个子类的对象。

请看代码示例:

未采用里氏替换原则

package com.std.www.designPattern.principle;



class Student {

    public void addStudent(){
        System.out.println("增加了一名学生");
    }
    public void removeStudent(){
        System.out.println("移除了一名学生");
    }
}
class StudentDao{
    private Student student;

    public void setStudent(Student student) {
        this.student = student;
    }

    public void add(){
        student.addStudent();
    }
    public void remove(){
        student.removeStudent();
    }
}
class SquadLeader{
    public void addStudent() {
        System.out.println("增加了一名班长");
    }
    
    public void removeStudent() {
        System.out.println("移除了一名班长");
    }
}

public class Client {
    public static void main(String[] args) {
        StudentDao studentDao=new StudentDao();
        studentDao.setStudent(new Student());
        studentDao.add();
        studentDao.remove();
    }
}

 采用里氏替换原则

package com.std.www.designPattern.principle;


abstract class BaseStudent{
    public abstract void addStudent();
    public abstract void removeStudent();
}

class Student extends BaseStudent{

    public void addStudent(){
        System.out.println("增加了一名学生");
    }
    public void removeStudent(){
        System.out.println("移除了一名学生");
    }
}
class StudentDao{
    private BaseStudent student;

    public void setStudent(BaseStudent student) {
        this.student = student;
    }

    public void add(){
        student.addStudent();
    }
    public void remove(){
        student.removeStudent();
    }
}
class SquadLeader extends BaseStudent{
    public void addStudent() {
        System.out.println("增加了一名班长");
    }

    public void removeStudent() {
        System.out.println("移除了一名班长");
    }
}

public class Client {
    public static void main(String[] args) {
        StudentDao studentDao=new StudentDao();
        studentDao.setStudent(new Student());
        studentDao.add();
        studentDao.remove();
        studentDao.setStudent(new SquadLeader());
        studentDao.add();
        studentDao.remove();
    }
}

里氏替换原则要求继承尽量不重写父类的方法,而且尽量使用关联,聚合,组合等方式代替继承,符合开闭原则,对于两个功能重复的模块,我们可以剥离出一个更基础的模块来,然后让这两个模块继承该模块,如果新增一个例如副班长模块,我们只需继承而无需修改源代码

 开闭原则

软件实体对扩是开放的,但对修改是关闭的,即在不修改一个软件的实体的基础上去扩展其功能

请看代码示例:

未采用开闭原则

package com.std.www.designPattern.principle;

class Student{

    public void addStudent(){
        System.out.println("增加了一名学生");
    }
    public void removeStudent(){
        System.out.println("移除了一名学生");
    }
    public void exchange(){
        System.out.println("交换一名学生");
    }
}

采用开闭原则

package com.std.www.designPattern.principle;

class Student{

    public void addStudent(){
        System.out.println("增加了一名学生");
    }
    public void removeStudent(){
        System.out.println("移除了一名学生");
    }
}

class NewStudent extends Student{
    public void exchangeStudent(){
        System.out.println("交换了一名学生");
    }
}

从上面例子看出,第一种方式修改了的Student的源代码,而第二种方式没有修改,而是创建一个新类对原来的Student进行功能扩展,而并没有修改原来Student的源代码

迪米特法则

一个软件实体对其它实体的引用越少越好,或者说如果这两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用,而是通过引入一个第三者发生间接交互。

请看代码示例:

未采用迪米特法则

package com.std.www.designPattern.principle;

import java.util.ArrayList;
import java.util.List;

class DBConnection{
    public void getDBConnection(){
        System.out.println("打开数据库连接");
    }
    public void closeDbConnection(){
        System.out.println("关闭数据库连接");
    }
}
class StudentDisplay{
    public void addStudent(){
        DBConnection dbConnection=new DBConnection();
        dbConnection.getDBConnection();
        System.out.println("添加一名学生");
        dbConnection.closeDbConnection();
    }
    public void removeStudent(){
        DBConnection dbConnection=new DBConnection();
        dbConnection.getDBConnection();
        System.out.println("移除一名名学生");
        dbConnection.closeDbConnection();
    }
    public void displayStudent(){
        DBConnection dbConnection=new DBConnection();
        dbConnection.getDBConnection();
        System.out.println("输出学生列表");
        dbConnection.closeDbConnection();
    }
}
class TeacherDisplay{
    public void addTeacher(){
        DBConnection dbConnection=new DBConnection();
        dbConnection.getDBConnection();
        System.out.println("添加一名学生");
        dbConnection.closeDbConnection();
    }
    public void removeTeacher(){
        DBConnection dbConnection=new DBConnection();
        dbConnection.getDBConnection();
        System.out.println("移除一名名学生");
        dbConnection.closeDbConnection();
    }
    public void displayTeacher(){
        DBConnection dbConnection=new DBConnection();
        dbConnection.getDBConnection();
        System.out.println("输出学生列表");
        dbConnection.closeDbConnection();
    }
}
public class Client {
    public static void main(String[] args) {
        StudentDisplay studentDisplay=new StudentDisplay();
        studentDisplay.displayStudent();
        TeacherDisplay teacherDisplay=new TeacherDisplay();
        teacherDisplay.displayTeacher();
    }
}

 采用迪米特法则

package com.std.www.designPattern.principle;

import java.util.ArrayList;
import java.util.List;

class DBConnection{
    public void getDBConnection(){
        System.out.println("打开数据库连接");
    }
    public void closeDbConnection(){
        System.out.println("关闭数据库连接");
    }
}
class PersonDao{
    public void add(String type){
        DBConnection dbConnection=new DBConnection();
        dbConnection.getDBConnection();
        System.out.println("添加一名"+type);
        dbConnection.closeDbConnection();
    }
    public void remove(String type){
        DBConnection dbConnection=new DBConnection();
        dbConnection.getDBConnection();
        System.out.println("移除一名"+type);
        dbConnection.closeDbConnection();
    }
    public void getList(String type){
        DBConnection dbConnection=new DBConnection();
        dbConnection.getDBConnection();
        System.out.println("返回+"+type+"+列表");
        dbConnection.closeDbConnection();
    }
}
class StudentDisplay{
    public void addStudent(){
        PersonDao student=new PersonDao();
        student.add("学生");
    }
    public void removeStudent(){
        PersonDao student=new PersonDao();
        student.remove("学生");
    }
    public void displayStudent(){
        PersonDao student=new PersonDao();
        student.getList("学生");
        System.out.println("输出学生列表");
    }
}
class TeacherDisplay{
    public void addTeacher(){
        PersonDao teacher=new PersonDao();
        teacher.add("老师");
    }
    public void removeTeacher(){
      PersonDao teacher=new PersonDao();
      teacher.remove("老师");
    }
    public void displayTeacher(){
        PersonDao teacher=new PersonDao();
        teacher.remove("老师");
        System.out.println("输出老师列表");
    }
}
public class Client {
    public static void main(String[] args) {
        StudentDisplay studentDisplay=new StudentDisplay();
        studentDisplay.displayStudent();
        TeacherDisplay teacherDisplay=new TeacherDisplay();
        teacherDisplay.displayTeacher();
    }
}

上面增加了一个中间类,让两个展示类通过这个中间类和数据库连接类进行交互,使得两个类解耦合,原本两个展示类都和数据库连接类交互,当新增一个数据库类或者展示类都可以通过这个中间类进行交互

合成复用原则

在复用功能时,应该尽量多使用组合和聚合关联关系,尽量少使用甚至不适用继承关系

请看代码示例:

未采用合成复用原则

package com.std.www.designPattern.principle;

class Student{
    public void addStudent(){
        System.out.println("添加一名学生");
    }
    public void removeStudent(){
        System.out.println("移除一名学生");
    }
}
class Teacher extends Student{
    public void addTeacher(){
        System.out.println("添加一名老师");
    }
    public void removeTeacher(){
        System.out.println("移除一名老师");
    }
}
class School extends Teacher{
    public void addSchoolPerson(){
        addStudent();
        addTeacher();
    }
    public void removeSchoolPerson(){
        removeStudent();
        removeTeacher();
    }
}
public class Client {
    public static void main(String[] args) {
        School school=new School();
        school.addSchoolPerson();
        school.removeSchoolPerson();
    }
}

 采用合成复用原则

package com.std.www.designPattern.principle;

class Student{
    public void addStudent(){
        System.out.println("添加一名学生");
    }
    public void removeStudent(){
        System.out.println("移除一名学生");
    }
}
class Teacher{
    public void addTeacher(){
        System.out.println("添加一名老师");
    }
    public void removeTeacher(){
        System.out.println("移除一名老师");
    }
}
class School {
    private Student student=new Student();
    private Teacher teacher=new Teacher();
    public void addSchoolPerson(){
        student.addStudent();
        teacher.addTeacher();
    }
    public void removeSchoolPerson(){
        student.removeStudent();
        teacher.removeTeacher();
    }
}
public class Client {
    public static void main(String[] args) {
        School school=new School();
        school.addSchoolPerson();
        school.removeSchoolPerson();
    }
}

这里使用聚集的方式代替继承,使得这三个类解耦合,提高了代码的复用性

这七大原则的核心思想是高内聚,低耦合