七大设计模式原则

1、开闭原则(Open-closed Principle)

开闭原则,是面向设计中最基础的设计原则。
一个软件实体类、模块、函数应该对扩展开放、对修改关闭
强调的是用抽象构建框架,用实现扩展细节。可以提高软件系统的可复用性和可维护性。

实例:

public interface ICourse {Integer getId();String getName();Double getPrice();}
public class JavaCourse implements ICourse{private Integer id;private String name;private Double price;public Integer getId() {return this.id;}public String getName() {return this.name;}public Double getPrice() {return this.price;}public JavaCourse(Integer id, String name, Double price) {this.id = id;this.name = name;this.price = price;}
}
public class JavaDiscountCourse extends JavaCourse {public JavaDiscountCourse(Integer id, String name, Double price) {super(id, name, price);}public Double getOriginPrice() {return super.getPrice();}public Double getPrice() {return super.getPrice() * 0.6;}}

2、本末倒置原则(Dependence Inversion Principle)

高层模块不应该依赖底层模块,二者都应该依赖其抽象。
抽象不应该依赖细节,细节应该依赖抽象。
本末倒置可以减少类与类之间的耦合性,提高系统的稳定性,提高代码的可读性和可维护性,降低修改程序造成的风险。

实例:

public interface ICourse {void study();}
public class JavaCourse implements ICourse{@Overridepublic void study() {System.out.println("学习Java");}}
public class PythonCourse implements ICourse{@Overridepublic void study() {System.out.println("学习Python");}}
/*** 方式一:依赖注入,每次学习一个新课程就多创建一个类*/
public class PersonOne {public void study(ICourse iCourse){iCourse.study();}public static void main(String[] args) {PersonOne personOne = new PersonOne();personOne.study(new JavaCourse());personOne.study(new PythonCourse());}
}
/*** 方式二:构造器注入,调用时每次都要创建实例*/
public class PersonTwo {private ICourse iCourse;public PersonTwo(ICourse iCourse) {this.iCourse = iCourse;}public void study() {iCourse.study();}public static void main(String[] args) {PersonTwo personTwo = new PersonTwo(new JavaCourse());personTwo.study();}
}
/*** 方式三:Setter方式注入*/
public class PersonThree {private ICourse iCourse;public void setCourse(ICourse iCourse) {this.iCourse = iCourse;}public void study() {iCourse.study();}public static void main(String[] args) {PersonThree personTwo = new PersonThree();personTwo.setCourse(new JavaCourse());personTwo.study();}
}

3、单一职责(Simple Responsibility Principle)

不要存在多于一个导致类变更的原因
一个对象应该只包含单一的职责,并且该职责被完整地封装在一个类中。

/*** course存在两种处理逻辑,这个地方修改代码*/
public class Course {public void study(String name){if("直播".equals(name)){System.out.println("不能快进");}else {System.out.println("2xx倍速");}}public static void main(String[] args) {Course course = new Course();course.study("直播");}}

修改下的代码,这样把两个课程给分开控制。

public class LiveCourse {public void study(String name){System.out.println("不能快进");}
}
public class ReplayCourse {public void study(String name){System.out.println("2xx倍速");}
}
public class Test {public static void main(String[] args) {LiveCourse liveCourse = new LiveCourse();liveCourse.study("直播");ReplayCourse replayCourse = new ReplayCourse();replayCourse.study("测试");}}`在这里插入代码片`

4、接口隔离原则(Interface Segregation Principle)

用多个专门的接口,而不使用单一的接口,客户端不应该依赖它不需要的接口

  • 一个类对一类的依赖应该建立在最小的接口上
  • 建立单一接口,不要建立庞大的接口
  • 尽量细化接口,接口中的方法尽量少

实例:

public interface Animal {void eat();void fly();void swimming();
}
public class Bird implements Animal{@Overridepublic void eat() {}@Overridepublic void fly() {}@Overridepublic void swimming() {}
}
public class Dag implements Animal{@Overridepublic void eat() {}@Overridepublic void fly() {}@Overridepublic void swimming() {}
}

当dog不能飞,鸟儿不能游泳的时候,这个方法就会空,这时候需要根据动物行为设计不同的接口

public interface EatAnimal {void eat();}
public interface FlyAnimal {void fly();}
public interface SwimmingAnimal {void swimming();}
public class Dog implements SwimmingAnimal, EatAnimal{@Overridepublic void eat() {}@Overridepublic void swimming() {}
}

5、迪米特法则(Law of demeter LoD)

一个对象应该对其他对象保持最少的了解。只和朋友交流,不喝陌生人说话。
出现在成员变量、方法的输入、输出参数中的类都可以称为成员朋友类,出现在方法体内内部的类不属于朋友类。

实例:

public class Course {
}
public class Employee {public void checkNumOfCourse(List<Course> courseList) {System.out.println("课程数量" + courseList.size());}
}
public class Leader {public void CommandCheckNumber(Employee employee){List<Course> courseList = new ArrayList<Course>();for (int i = 0; i < 20; i++) {courseList.add(new Course());}employee.checkNumOfCourse(courseList);}public static void main(String[] args) {Leader leader = new Leader();Employee employee = new Employee();leader.CommandCheckNumber(employee);}
}

根据迪米特法则,Leader只想要结果,不需要和Course有直接的接触,所以这个地方修改

public class EmployeeCp {public void checkNumOfCourse() {List<Course> courseList = new ArrayList<Course>();for (int i = 0; i < 20; i++) {courseList.add(new Course());}System.out.println("课程数量" + courseList.size());}
}
public class LeaderCp {public void CommandCheckNumber(EmployeeCp employee){employee.checkNumOfCourse();}public static void main(String[] args) {LeaderCp leader = new LeaderCp();EmployeeCp employee = new EmployeeCp();leader.CommandCheckNumber(employee);}
}

6、里氏替换原则(Liskov Substitution Priciple)

如果针对一个类型为T1的对象O1,都有类型T2的对象O2,使得以T1定义的所有程序P在所有的对象O1都替换成O2时,程序P的行为没有发生变化,那么类型T2还是类型T1的子类型。
1)子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法
2)子类仲可以增加自己特有的方法
3)当子类的方法重载父类的方法时,方法的前置条件(入参)要比父类方法的输入参数更宽松
4)当子类的方法实现
父类的方法时,方法的后置条件(输出/返回值)要比父类更严格或相等

优点:
1)约束继承泛滥,开闭原则的一种体现
2)加签程序的健壮性,同时变更也可以做到好的兼容,提高程序的维护性、扩展性,降低需求变更时的风险

实例:

public class Rectangle {private Long height;private Long width;public Long getHeight() {return height;}public Long getWidth() {return width;}public void setHeight(Long height) {this.height = height;}public void setWidth(Long width) {this.width = width;}
}
public class Square extends Rectangle {private Long length;public Long getLength() {return length;}public void setLength(Long length) {this.length = length;}@Overridepublic Long getHeight() {return getLength();}@Overridepublic void setHeight(Long height) {setLength(height);}@Overridepublic Long getWidth() {return getLength();}@Overridepublic void setWidth(Long width) {setLength(width);}}
public class Test {public static void resize(Rectangle rectangle){while (rectangle.getWidth() >= rectangle.getHeight()){rectangle.setHeight(rectangle.getHeight()+1);System.out.printf("width: %s, height:%s", rectangle.getWidth(), rectangle.getHeight());}System.out.printf("width: %s, height:%s", rectangle.getWidth(), rectangle.getHeight());}public static void main(String[] args) {Rectangle rectangle = new Rectangle();rectangle.setWidth(20L);rectangle.setHeight(10L);resize(rectangle);//死循环Square square = new Square();square.setLength(10L);resize(square);}
}

当是正方形的时候,陷入死循环,违背里氏替换原则,父类替换成子类后结果不是预期。
修改代码,创建一个抽象四边形

public interface QuadRectangle {Long getWidth();Long getHeight();
}
public class RectangleCp implements QuadRectangle{private Long height;private Long width;public Long getHeight() {return height;}public Long getWidth() {return width;}public void setHeight(Long height) {this.height = height;}public void setWidth(Long width) {this.width = width;}
}
public class SquareCp implements QuadRectangle {private Long length;public Long getLength() {return length;}public void setLength(Long length) {this.length = length;}@Overridepublic Long getHeight() {return getLength();}@Overridepublic Long getWidth() {return getLength();}}

7、合成复用原则(Composite Reuse Principle)

尽量使用对象组合(has-a)/聚合(contain-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("创建商品");}}

如果这时候不只是mysql还有其他类型的数据库,违反开闭原则
修改代码:

public abstract class DBConnectionCp {public abstract String getConnection();
}
public class MysqlConnection extends DBConnection{@Overridepublic String getConnection() {return "mysql";}
}
public class OracleConnection extends DBConnection{@Overridepublic String getConnection() {return "Oracle";}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/10556.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HBase 源码编译部署包

1. 版本 Java 版本: 1.8.0_201 HBase 版本: hbase-2.5.5 2.打包 git clone https://github.com/apache/hbase.git cd hbase git checkout branch-2.5 编译整个工程的 tar 包&#xff0c;编译一次 10 分钟左右 mvn clean package assembly:single -DskipTests ll hbase-assemb…

设计模式【行为型】-- 责任链模式

责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;是一种行为型设计模式&#xff0c;它允许多个对象依次处理同一个请求&#xff0c;形成一条责任链。当客户端提交一个请求时&#xff0c;请求沿着责任链传递&#xff0c;直到有一个处理者能够处理该请求为止。…

对原型、原型链的理解

在 JavaScript 中是使用构造两数来新建一个对象的&#xff0c;每一个构造函数的内部都有一个 prototype 属性&#xff0c;它的属性值是一个对象&#xff0c;这个对象包含了可以由该构造西数的所有实例共享的属性和方法。当使用构造函数新建一个对象后&#xff0c;在这个对象的内…

【《React Hooks实战》——指导你使用hook开发性能优秀可复用性高的React组件】

使用React Hooks后&#xff0c;你很快就会发现&#xff0c;代码变得更具有组织性且更易于维护。React Hooks是旨在为用户提供跨组件的重用功能和共享功能的JavaScript函数。利用React Hooks&#xff0c; 可以将组件分成多个函数、管理状态和副作用&#xff0c;并且不必声明类即…

Python实现单例模式

一、介绍 单例模式是一种常见的设计模式&#xff0c;它保证一个类只能被实例化一次&#xff0c;并提供了一个全局访问点来获取这个唯一的实例。在Python中&#xff0c;可以通过使用装饰器、元类或模块等方式实现单例模式。 二、Python实现单例模式的6种方法 1、使用模块实现…

微软、OpenAI用上“数据永动机” 合成数据是晨曦还是暮光?

微软、OpenAI、Cohere等公司已经开始测试使用合成数据来训练AI模型。Cohere首席执行官Aiden Gomez表示&#xff0c;合成数据可以适用于很多训练场景&#xff0c;只是目前尚未全面推广。 已有的&#xff08;通用&#xff09;数据资源似乎接近效能极限&#xff0c;开发人员认为&a…

DoS攻击

DoS攻击&#xff08;拒绝服务攻击&#xff09; 拒绝服务攻击DoS(Denial of Service)&#xff1a;使系统过于忙碌而不能执行有用的业务并且占尽关键系统资源。 它是基于这样的思想&#xff1a;用数据包淹没本地系统&#xff0c;以打扰或严重阻止捆绑本地的服务响应外来合法的请…

Java类的默认构造函数

什么情况下存在默认构造函数 说明 如果一个Java类没有显式包含构造函数的声明&#xff0c;那么隐含着有一个默认构造函数。 示例 定义一个类B&#xff0c;没有显式声明构造函数&#xff0c;所以存在一个默认构造函数&#xff1a; package com.thb;public class B {public …

selenium浏览器驱动下载

Chrome谷歌浏览器 下载地址&#xff1a;http://chromedriver.storage.googleapis.com/index.html 不同的Chrome的版本对应的chromedriver.exe 版本也不一样&#xff0c;下载时不要搞错了。 如果是最新的Chrome, 下载最新的chromedriver.exe 就可以了。 Firefox火狐浏览器 驱…

扫地机语音提示芯片,智能家居语音交互首选方案,WT588F02B-8S

智能家居已经成为现代家庭不可或缺的一部分&#xff0c;而语音交互技术正是智能家居的核心。在智能家居设备中&#xff0c;扫地机无疑是最受欢迎的产品之一。然而&#xff0c;要实现一个更智能的扫地机&#xff0c;需要一颗语音提示芯片&#xff0c;以提供高质量的语音交互体验…

Android Studio 的版本控制Git

Android Studio 的版本控制Git。 Git 是最流行的版本控制工具&#xff0c;本文介绍其在安卓开发环境Android Studio下的使用。 本文参考链接是&#xff1a;https://learntodroid.com/how-to-use-git-and-github-in-android-studio/ 一&#xff1a;Android Studio 中设置Git …

深度学习:梯度裁剪简介

深度学习&#xff1a;梯度裁剪简介 梯度裁剪简介设置范围值裁剪通过 L2 范数裁剪 附 在深度学习领域&#xff0c;梯度裁剪是一个常用的技巧&#xff0c;用于防止梯度过小或过大。下面简单介绍一下 梯度裁剪的原理与方法。 梯度裁剪简介 在深度学习模型的训练过程中&#xff0…

Linux系统安装部署Jenkins详细教程(图文讲解)

前言&#xff1a;最近需要使用Jenkins部署项目&#xff0c;所以想出一篇关于如何使用Linux系统安装部署Jenkins的相关教程&#xff0c;整体部署过程还是挺顺利的&#xff0c;特此分享一下&#xff01; 目录 一、安装JDK11和Tomcat11 二、准备Jenkins安装包 三、部署Jenkins…

安全杂记 - js中的this关键字

javascript里什么是this this是js中的一个关键字&#xff0c;它是函数在运行时生成的一个内部对象&#xff0c;是属性和方法。 this就是属性或方法“当前”所在的对象&#xff0c;也就是调用函数的那个对象 this的使用场合 1.函数调用 <script>var a100;function test…

访问:http://localhost:8070/actuator/bus-refresh 问题

1、请求发送不出去 原因&#xff1a; 自己 config-server端 application.yml 配置的端口号是8888&#xff0c;访问server修改为配置的端口号 2、请求报错405 几个解决办法&#xff1a; 1、版本问题变为busrefresh 2、bus-refresh加单引号或双引号尝试 3、加配置尝试&#xff1a…

TypeScript -- 基础类型

文章目录 TypeScript -- 基础类型let 和 const基本类型写法布尔类型 -- boolean数字类型 -- number字符串类型 -- string数组类型元组类型枚举类型 -- enum任意类型 -- any空值 -- voidNull 和 Undefined不存在的类型 -- never对象 -- object类型断言 TypeScript – 基础类型 1…

【Linux下6818开发板(ARM)】SecureCRT串口和交叉编译工具(巨细版!)

(꒪ꇴ꒪ ),hello我是祐言博客主页&#xff1a;C语言基础,Linux基础,软件配置领域博主&#x1f30d;快上&#x1f698;&#xff0c;一起学习&#xff01;送给读者的一句鸡汤&#x1f914;&#xff1a;集中起来的意志可以击穿顽石!作者水平很有限&#xff0c;如果发现错误&#x…

h5应用调用企业微信api过程(获取当前外部联系人userId方法)

调用过程: 通过OAuth2授权链接进入页面并完成登录调用后台获取企业签名接口 并进行 wx.config() 注册在 wx.ready() 中继续 企业微信应用身份认证, 调用后台企业微信应用签名接口获取签名&#xff0c;在 wx.agentConfgi() 中注册在 wx.invoke() 中调用需要使用的api方法 下面…

【网络编程】(TCP流套接字编程 ServerSocket API Socket API 手写TCP版本的回显服务器 TCP中的长短连接)

文章目录 网络编程TCP流套接字编程ServerSocket APISocket APITCP中的长短连接手写TCP版本的回显服务器 网络编程 TCP流套接字编程 TCP提供的API主要是两个类:ServerSocket 和 Socket . TCP不需要一个类来表示"TCP数据报"因为TCP不是以数据报为单位进行传输的.是以…

管理类联考——数学——趣味篇——可视化

Manim: 一个数学可视化的动画引擎 官网&#xff1a;https://3b1b.github.io/manim/index.html 名词解析 python3.7是python语言的解释器, 运行python程序的环境必备品. 这个没啥说的,大家都能懂. 虽然官方建议3.7,但是我用3.8发现也没问题.考虑未来的历史进程,大伙最好还是装…