JAVA全栈开发 JDBC、反射、设计者模式

一、JDBC

【1】JDBC概述

1.1什么是jdbc

Java DataBase Connectivity是一种用于执行SQL语句的Java API,它由一组用Java语言编写的类和接口组成。通过这些类和接口,JDBC把SQL语句发送给不同类型的数据库进行处理并接收处理结果。

1.2jdbc的作用

提供java 操作不同数据库的技术

1.3JDBC两大类

对Java开发人员而言是API,对数据库提供商而言是接口。

面向开发人员:作为API,JDBC为程序开发提供标准的接口。

面向数据库厂商:作为接口,让数据库厂商按标准方法来实现数据库连接与操作(数据库驱动程序)。

在这里插入图片描述

1.4JDBC工作过程

在这里插入图片描述

【2】Jdbc数据库连接

  1. 下载Jar

下载jarhttps://blog.csdn.net/qq_35368140/article/details/131246017

  1. 引入Jar (包括jdbc 驱动程序 )

引入jarhttps://blog.csdn.net/qq_43599841/article/details/127368168%5D

  1. JDBC 使用步骤

    ​ 1. 加载驱动 (只会运行一次:static)

    ​ 2. 获得链接对象 Connection

    ​ 3. 获得执行对象 Statement

    ​ 4. 执行sql并获得结果集(ResultSet)

    ​ 5. 处理结果集

    6.释放资源

    public static void main(String[] args) throws SQLException {//1.注册驱动 告诉jdbc我们使用哪一个数据库厂商的驱动//驱动管理器专门注册驱动(需要传递一个驱动对象)DriverManager.registerDriver(new com.mysql.jdbc.Driver());//2. 建立驱动连接//url:链接数据库的地址  jdbc:mysql://localhost:3306/数据库的名字//user:用户名//password:密码//面向接口编程Connection connection = (Connection) DriverManager.getConnection("jdbc:mysql://localhost:3306/j352", "root", "");//3.创建向数据库发送sql的statement对象Statement st = connection.createStatement();//4.发送sql后获得一个封装了查询结果的ResultSet对象ResultSet rs = st.executeQuery("select * from student limit 1");//5.解析ResultSet对象获得结果if(rs.next()) {System.out.println("id:"+rs.getObject("Id"));System.out.println("name:"+rs.getObject("StudentName"));System.out.println("age:"+rs.getObject("age"));}//释放资源rs.close();st.close();connection.close();}
    

二、Api详解

1 注册驱动

DriverManager.registerDriver(new com.mysql.jdbc.Driver());不建议使用

原因有2个:

>导致驱动被注册2次。

>强烈依赖数据库的驱动jar

解决办法:

注册驱动的第二种方式

Class.forName(“com.mysql.jdbc.Driver”);

2 获取链接

static Connection getConnection(String url, String user, String password)试图建立到给定数据库 URL 的连接。参数说明:url 需要连接数据库的位置(网址) user用户名 password 密码例如:getConnection("jdbc:mysql://localhost:3306/数据库名称", "root", "");URL:SUN公司与数据库厂商之间的一种协议。jdbc:mysql://localhost:3306/数据库名称协议 子协议 IP : 端口号 数据库
常用数据库URL地址的写法: 
Oracle写法:jdbc:oracle:thin:@localhost:1521:sid 
SqlServer jdbc:microsoft:sqlserver://localhost:1433; DatabaseName=sid 
MySql jdbc:mysql://localhost:3306/sid 
Mysql的url地址的简写形式: jdbc:mysql:///sid 
常用属性:useUnicode=true&characterEncoding=UTF-8

接口的实现在数据库驱动中。所有与数据库交互都是基于连接对象的。

Statement createStatement(); //创建操作sql语句的对象

3 API详解:java.sql.Statement接口: 操作sql语句,并返回相应结果

String sql = “某SQL语句”;

获取Statement语句执行平台:Statement stmt = con.createStatement();

常用方法:

int executeUpdate(String sql); --执行insert update delete语句.

ResultSet executeQuery(String sql); --执行select语句.

boolean execute(String sql); --仅当执行select并且有结果时才返回true,执行其他的语句返回false.

 //1.注册驱动Class.forName("com.mysql.jdbc.Driver");//2.获取链接Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbc","root","root");//3.获取代表向数据库发送sql的statement对象Statement st = conn.createStatement();String sql="insert into student(name,age) values('奥利给','20')";//4.发送sql//返回影响的行数 大于0代表执行成功int result = st.executeUpdate(sql);if(result>0) {System.out.println("插入成功");}//5.释放资源st.close();conn.close();

4 API详解:处理结果集(注:执行insert、update、delete无需处理)

ResultSet实际上就是一张二维的表格,我们可以调用其boolean next()方法指向某行记录,当第一次调用next()方法

时,便指向第一行记录的位置,这时就可以使用ResultSet提供的getXXX(int col)方法(与索引从0开始不同个,列从1

开始)来获取指定列的数据:

rs.next();//指向第下一行

rs.getObject(1);//获取第一行第一列的数据

在这里插入图片描述

常用方法:

n Object getObject(int index) / Object getObject(String name) 获得任意对象

n String getString(int index)/ String getString(String name) 获得字符串

n int getInt(int index)/int getInt(String name) 获得整形

n double getDouble(int index)/ double getDouble(String name) 获得双精度浮点型

在这里插入图片描述

5 释放资源

与IO流一样,使用后的东西都需要关闭!关闭的顺序是先得到的后关闭,后得到的先关闭。

rs.close();  //结果集stmt.close(); //statement对象con.close(); //连接对象

6 关闭异常处理

public static void main(String[] args) throws Exception {//1.注册驱动Class.forName("com.mysql.jdbc.Driver");//2.获取链接Connection conn =null;Statement st=null;ResultSet rs=null;try {//2.获取链接conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbc","root","root");//3.获取代表向数据库发送sql的statement对象st = conn.createStatement();String sql="select id,name,age from student";//4.发送sqlrs = st.executeQuery(sql);//定义集合封装Student数据List<Student> list=new ArrayList<Student>();while(rs.next()) {//查询出来的结果封装到对象中Student s=new Student();s.setId(rs.getInt("id"));s.setAge(rs.getInt("age"));s.setName(rs.getString("name"));list.add(s);}System.out.println(list);}finally {//5.释放资源//关闭资源之前一定要判断if(rs!=null) {try {rs.close();}catch (Exception e) {e.printStackTrace();}//让jvm回收没有被关闭的rs对象rs=null;}if(st!=null) {try {st.close();}catch (Exception e) {e.printStackTrace();}st=null;}if(conn!=null) {try {conn.close();}catch (Exception e) {e.printStackTrace();}conn=null;}}}}

三、封装JDBC

  1. 提交公共方法(获取连接,释放资源)
  2. 将这两方法,提到一个类中
  3. 将数据库连接url, 用户名,密码,放到文件中,把它变成可以配置的

步骤1,步骤2:

public class JdbcUtils {static {//1.注册驱动  告诉jdbc我们使用哪一个数据库厂商的驱动try {Class.forName("com.mysql.jdbc.Driver");} catch (ClassNotFoundException e) {throw new RuntimeException(e);}}// 项目一旦交付// 公司(乙)  做项目(产品)  =》   给别人做项目(甲)//                                部署(运维)-》 配置文件public static Connection GetConnection() throws ClassNotFoundException, SQLException {//2.通过驱动管理器获取一个链接Connection connection = (Connection) DriverManager.getConnection("jdbc:mysql://localhost:3306/j352", "root", "");return  connection;}public static void release(Connection conn, Statement sm , ResultSet rs){if(rs!=null){try {rs.close();} catch (SQLException e) {e.printStackTrace();}rs =null; //让jvm来回收它}if(sm!=null){try {sm.close();} catch (SQLException e) {e.printStackTrace();}sm =null; //让jvm来回收它}if(conn!=null){try {conn.close();} catch (SQLException e) {e.printStackTrace();}conn =null; //让jvm来回收它}}
}

步骤3: 将数据库连接url, 用户名,密码,放到文件中,把它变成可以配置的

Properties

在这里插入图片描述

使用properties后的代码

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/j352
username=root
password=
public class JdbcUtils {private static Properties properties = new Properties();static {//1.注册驱动  告诉jdbc我们使用哪一个数据库厂商的驱动try {//1.1 读取文件中的信息FileInputStream in = null;try {in = new FileInputStream("src\\jdbc.properties");} catch (FileNotFoundException e) {throw new RuntimeException(e);}// 1.2  Properties对象中有一个load方法properties.load(in);  //将文件相关的信息加载到properties 对象中Class.forName(properties.getProperty("driverClassName"));} catch (ClassNotFoundException e) {throw new RuntimeException(e);} catch (IOException e) {throw new RuntimeException(e);}}// 项目一旦交付// 公司(乙)  做项目(产品)  =》   给别人做项目(甲)//                                部署(运维)-》 配置文件public static Connection GetConnection() throws ClassNotFoundException, SQLException, IOException {// 读取文件中的数据 jdbc.properties ,进行使用//String getProperty(String key)//2.通过驱动管理器获取一个链接Connection connection = (Connection) DriverManager.getConnection(properties.getProperty("url"),properties.getProperty("username"), properties.getProperty("password"));return  connection;}public static void release(Connection conn, Statement sm , ResultSet rs){if(rs!=null){try {rs.close();} catch (SQLException e) {e.printStackTrace();}rs =null; //让jvm来回收它}if(sm!=null){try {sm.close();} catch (SQLException e) {e.printStackTrace();}sm =null; //让jvm来回收它}if(conn!=null){try {conn.close();} catch (SQLException e) {e.printStackTrace();}conn =null; //让jvm来回收它}}
}

四、SQL注入

登录

如果执行的sql语句,是用字符串进行拼接, 就容易出sql 注入

在这里插入图片描述

如何防止sql注入

  1. 输入时,不让它输入特殊字符 ,正则(只输入字母或数字 )

  2. 执行sql时不用sql拼接,而使用参数化查询

    public int login(String username, String pwd) {int result = 0;Connection conn = null; //创建连接
    //        Statement statement = null;PreparedStatement pst = null;ResultSet resultSet = null;try {conn = JdbcUtils.GetConnection();// 查询String sql = "select * from user where username=? and pwd=? ";pst = conn.prepareStatement(sql);pst.setString(1,username);pst.setString(2,pwd);System.out.println(sql);resultSet = pst.executeQuery(sql);if (resultSet.next()) {result = 1;}}  catch (ClassNotFoundException e) {result = 2;e.printStackTrace();
    //                throw new RuntimeException(e);} catch (SQLException e) {result = 3;e.printStackTrace();} catch (IOException e) {result = 4;e.printStackTrace();}finally {JdbcUtils.release(conn,pst,resultSet);}return  result;}

五、Jdbc控制事务

1.java中事务的控制

conn.setAutoCommit(false) == start transaction;

conn.commit() == commit;

conn.rollback(); == rollback;

public class TransactionDemo {public static void main(String[] args) {// 1. 获取连接Connection connection =  null;PreparedStatement statement = null;ResultSet resultSet = null;try{connection = JdbcUtils.GetConnection();//2. 事务开启connection.setAutoCommit(false);String sql = "update user set age = 18 where username='admin'";statement = connection.prepareStatement(sql);statement.executeUpdate(); //执行sql//            int x= 1/ 0 ;String sql2 = "update user set age = 28 where username='doubleyong'";statement = connection.prepareStatement(sql2);statement.executeUpdate(); //执行sql// 3。提交事务connection.commit();}catch (Exception e){//关闭事务try {connection.rollback();
//                connection.commit();} catch (SQLException ex) {throw new RuntimeException(ex);}e.printStackTrace();}finally {JdbcUtils.release(connection,statement,resultSet);}}
}

2.事务的回滚点

回滚到指定位置

savepoint = conn.setSavepoint();

 public static void main(String[] args) {// 1. 获取连接Connection connection =  null;PreparedStatement statement = null;ResultSet resultSet = null;Savepoint savepoint=null;try{connection = JdbcUtils.GetConnection();//2. 事务开启connection.setAutoCommit(false);String sql = "update user set age = 66 where username='admin'";statement = connection.prepareStatement(sql);statement.executeUpdate(); //执行sql//设置一个事务的回滚点savepoint = connection.setSavepoint();int x= 1/ 0 ;String sql2 = "update user set age = 77 where username='doubleyong'";statement = connection.prepareStatement(sql2);statement.executeUpdate(); //执行sql// 3。提交事务connection.commit();}catch (Exception e){//关闭事务try {connection.rollback(savepoint); //回滚到指定事物点connection.commit(); //回滚后,如何 还是有sql执行,必须 加上commit } catch (SQLException ex) {throw new RuntimeException(ex);}e.printStackTrace();}finally {JdbcUtils.release(connection,statement,resultSet);}}

六、反射

【1】反射概念

反射: 加载类,反射出类的各个组成部分 构造方法,属性(非静态属性和静态属性),方法(非静态方法,静态方法)

java 反射机制: 是在运行状态中(Class对象), 对于任何类,都能能够知道这个类的所有的属性和方法; 对于任意一个对象,能够调用它的任意属性和方法;这种动态获取信息的方式,就称之反射.

【2】类加载

当程序要使用某个类时,如果这个类还没有加载内存中,则系统会通过加载,连接,初始化三个步骤来实现对这个类的初始化。

加载 :

将class 文件加载到内存中,并为之创建一个Class对象(将class文件的内容放到一个对象中,而对象的名字刚好就是Class)

​ 任何类被使用时,系统都会建立一个Class对象.

连接

​ 验证: 是否有正确的内部结构 ,并和其它协调一致

​ 准备 : 负责为类的静态成员分配内存,并设置默认初始化值

​ 解析: 将类的二进制数据中的符号引用替换成直接引用

初始化

​ 就是之前的初始化步骤

2.1类加载的时机

  1. 创建类的实例

  2. 访问类的静态变量或给静态变量赋值

  3. 调用类的静态方法

  4. 初始化某个类的子类

  5. java命令,运行某个类

  6. 使用反射方式强制创建某个类或接口对应的Class对象

2.2类加载器

负责将class 文件加载到内存中,并为之创建一个Class对象,如果了解类加载器的机制,可以的更好的理解程序的运行

类加载器的组成:

根类加载器: bootstrap classLoader

​ 也被称为引导类加载类,负责Java核心类的加载

​ 比如: System, String 等,在 JDK 中的JRE 中 lib 中的 rt.jar文件中

扩展类加载器: extension classLoader

​ 负责jre的扩展目录中的jar的加载

系统类加载器: System classLoader

​ 负责在JVM启动时加载来自java 命令的class文件

2.3获取Class对象的方式

开发: 使用第三种.

​ 为什么? 因为第三种是一个字符 串,而不是具体类名,这种的话就可以将这个值放到配置文件中,方便对它修改.

//方法1:Person p = new Person();Class c = p.getClass();Person p1 = new Person();Class c1 = p.getClass();System.out.println(p==p1);  //falseSystem.out.println(c==c1);  //true//方法2:Class c2 = Person.class;System.out.println(c == c2); //true// 方法3// Class对象中的静态方法//ClassNotFoundException  必须写包名Class c3 = Class.forName("com.demo1.Person");System.out.println(c==c3);

2.4获取类的加载器

//1. 如何获取 类的加载器//1.1 首先得到Class对象Class c = Person.class;//1.2 获取类的加载器ClassLoader classLoader = c.getClassLoader();System.out.println(classLoader);

2.5使用类加载器加载其它的文件

注:小心路径问题,最好是将方法放到 resource 目录下

https://blog.csdn.net/weixin_48052161/article/details/115151874

 Class c = User.class;//1.2 获取类的加载器ClassLoader classLoader = c.getClassLoader();System.out.println(classLoader);// 类加载器加载其它的文件InputStream in = classLoader.getResourceAsStream("jdbc.properties");System.out.println(in);

【3】类加载的原理

类加载是Java虚拟机(JVM)对类文件进行加载、验证、准备、解析和初始化等一系列操作的过程。类加载的原理包括以下几个步骤:1.加载:在类加载过程中,JVM会根据类的全限定名来获取类的字节码文件,并将其读取到内存中。2.验证:在验证阶段,JVM会对字节码文件进行验证,确保其符合Java语言规范和安全要求。验证包括文件格式验证、元数据验证、字节码验证和符号引用验证等。3.准备:在准备阶段,JVM会为类的静态变量分配内存,并设置默认初始值(例如0、null等)。4.解析:在解析阶段,JVM会将类的符号引用转换为直接引用,以便于后续的内存访问。解析过程包括类、接口、字段和方法等的解析。5.初始化:在初始化阶段,JVM会执行类的初始化代码,包括静态变量的赋值和静态代码块的执行。在这个阶段,类的初始化按照严格的顺序进行,并且只会执行一次。类加载过程是按需进行的,即当程序需要使用某个类时,JVM才会进行相应的类加载操作。同时,JVM还采用了双亲委派模型来进行类加载,即先委派给父类加载器尝试加载,只有在父类加载器无法加载时,才由子类加载器尝试加载。通过类加载的原理,Java实现了动态扩展和灵活的类加载机制,使得开发人员可以根据需要动态加载和使用类,实现了面向对象编程的核心特性之一:封装和复用

先做了解,第四阶段着重讲

【4】反射构造器

反射构造器: 通过Class对象,获取构造方法

 Class c = Person.class;//获取构造方法// Constructor<?>[] getConstructors() : 返回所有的构造方法 Constructor 类的对象  只能获取 public修饰的构造方法//返回包含一个数组 Constructor对象反射由此表示的类的所有公共构造 类对象。
//        Constructor[] constructors = c.getConstructors();//c.getDeclaredConstructors(); 获取 所有构造方法
//        Constructor[] constructors = c.getDeclaredConstructors();
//        for(Constructor constructor:constructors){
//            System.out.println(constructor);
//        }//获取单个构造方法// getConstructor(类<?>... parameterTypes): 只能得到public修饰
//        Constructor constructor = c.getConstructor(String.class);Constructor constructor = c.getDeclaredConstructor(String.class);System.out.println(constructor);//Constructor<T> getConstructor(类<?>... parameterTypes)//返回一个 Constructor对象,该对象反映 Constructor对象表示的类的指定的公共 类函数。// 根据构造方法,创建实例对象//java.lang.IllegalAccessException 构造方法是私有的,创建实现,会报非法异常// 解决方案:constructor.setAccessible(true); //跳过java语法检查Object obj = constructor.newInstance("张三");System.out.println(obj);

【5】反射属性

反射构造器: 通过Class对象,获取成员属性

   public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {Class c = Person.class;//public Field[] getFields() 返回包含一个数组Field对象反射由此表示的类或接口的所有可访问的公共字段类对象。
//        Field[] fields = c.getFields();
//        for(Field field : fields){
//            System.out.println(field);
//        }//public Field[] getDeclaredFields() : 获取所有属性
//        Field[] fields = c.getDeclaredFields();
//        for(Field field : fields){
//            System.out.println(field);
//        }//NoSuchFieldException
//        Field field= c.getField("name");
//        System.out.println(field);//        Field field= c.getDeclaredField("name");
//        System.out.println(field);// 没有对象就没有属性// 要使用属性,必须 要有对象Constructor constructor = c.getDeclaredConstructor();Object obj = constructor.newInstance(); //创建对应的对象Field namefield = c.getDeclaredField("name");Field agefield = c.getDeclaredField("age");Field addressfield = c.getDeclaredField("address");//IllegalAccessExceptionnamefield.setAccessible(true);namefield.set(obj,"唐姐");agefield.set(obj,18);addressfield.set(obj,"成都");System.out.println(obj);}

【6】反射方法

反射构造器: 通过Class对象,获取成员方法

七、JDBC 与反射结合

封装了两个方法: 增删改 excuteUpdate, 查询 excuteQuery

public class JdbcUntils {static {//1.注册驱动  告诉jdbc我们使用哪一个数据库厂商的驱动try {Class.forName("com.mysql.jdbc.Driver");} catch (ClassNotFoundException e) {throw new RuntimeException(e);}}//写一个jdbc 工具类Connection connection = null;PreparedStatement st = null;ResultSet rs = null;//分析:// 当前方法写完了,发现sql 语句是不是直接传过来,可以如果 有参数,直接进行sql拼接会产生sql注入风险// 所以,就考虑使用参数化// 将数据,传过来,传来后,使用PreparedStatement添加参数public int excuteUpdate(String sql,Object... params)   {int result = -1;try {//2. 创建连接connection = getConnection();//3. 创建statement对象//这个里包括了? ,所以需要参数指定st = connection.prepareStatement(sql);//要把参数加到PreparedStatement对象中//pst.setString(1,username);// pst.setString(2,pwd);for (int i = 0; i < params.length; i++) {st.setObject((i + 1), params[i]);}result = st.executeUpdate();//4. release 释放资源release();}catch (SQLException e){e.printStackTrace();result = -1;}finally {return result;}}public <T>  List<T> excuteQuery(String sql,Class<T> c,Object... prarms){//创建一个集合,存放所有的结果对象List<T> list  = new ArrayList<>();try {connection = getConnection();//	3. 获得执行对象  Statement// 查询 里的sql语句也可以能有参数st = connection.prepareStatement(sql);//添加参数for (int i = 0; i < prarms.length; i++) {st.setObject((i + 1), prarms[i]);}//	4. 执行sql并获得结果集(ResultSet)rs = st.executeQuery();// 4.1 得到结果集的元数据ResultSetMetaData ms = rs.getMetaData();//列的数量int colCount = ms.getColumnCount(); // 处理结果while (rs.next()){
//                int i = 1;//添加一个 T类的实例T t = c.getDeclaredConstructor().newInstance();// 1. 得到结果集,列名数组//2. 循环列名//   循环体里,根据列名,去找对象的对应的字段 ,然后在进行赋值for(int i=1;i<=colCount;i++){Object value = rs.getObject(i);if(value!=null){//将这对应的值,放到对象对应的字段中String colName = ms.getColumnName(i);//通过反射,设置字段的值//要求结果的列名,与实体对象的属性(字段名)相同Field field = c.getDeclaredField(colName);// 跳出java的语法检查 field.setAccessible(true);// 给字段设置对应的值 field.set(t,value);}}list.add(t);//给实例对象的每个属性,赋值// 方法一: 获取所有字段进行赋值,这个要求字段与数据的列的顺序要求一致
//                Field[] Fields = c.getDeclaredFields(); //获取所有的字段
//                for(Field field : Fields){
//                    //缺点: 实体的字段 与数据查询 出来的字段要一一对应
//                    //思路: 如果不对应怎么?
//                    // 最好,可以得到结果集的列名,根据列名,给对应的字段赋值
//
//                    // 这里值 ,应该从结果集
//                    field.set(t,rs.getObject(i++));
//                }//T对象加入到list中}// 	5. 处理结果集release();}catch (Exception e){e.printStackTrace();list = null;} finally {return list;}}//创建连接public Connection getConnection() throws SQLException {//2.通过驱动管理器获取一个链接Connection connection = (Connection) DriverManager.getConnection("jdbc:mysql://localhost:3306/j352", "root", "");return  connection;}//释放资源public  void release(){if(rs!=null){try {rs.close();} catch (SQLException e) {e.printStackTrace();}rs =null; //让jvm来回收它}if(st!=null){try {st.close();} catch (SQLException e) {e.printStackTrace();}st =null; //让jvm来回收它}if(connection!=null){try {connection.close();} catch (SQLException e) {e.printStackTrace();}connection =null; //让jvm来回收它}}}

八、设计原则

1)创建软件应用程序是为了满足不断变化和发展的需求。一个成功的应用程序还应该提供一种简单的方法来扩展它以满足不断变化的期望。如果在设计和开发软件时应用一组面向对象的设计原则和模式,则可以避免或解决这些常见问题。

2)面向对象的设计原则也被称为 SOLID 。在设计和开发软件时可以应用这些原则,以便创建易于维护和开发的程序。

SOLID 原则包括,单一职责原则、开闭原则、里氏替换原则、接口隔离原则和依赖倒置原则。

单一职责原则:每个类只负责做一件事

专业的人做专业的事。每个类只负责做一件事

单一职责原则,其它就是“高内聚”的体现。

每个类只负责做一件事, 对外只提供一个功能,而引起类的变化 的原因应该只有一个。

开闭原则 : 对扩展开放,对修改关闭

核心思想:一个对象 对扩展开放,对修改关闭

对类的改动是通过增加代码进行,而不是修改代码

如何实现?这就需要借助于抽象 和多态。即把可能变化 的内容抽象 出来.

因为抽象的部分是相对稳定

里氏替换原则

子类可以扩展父类的功能,但不能改变父类原有的功能

子类继承父类时,除添加新的方法完成新增功能外,尽量不要重写父类的方法。

接口隔离原则

别人不需要的东西不要强加给人家。

接口隔离原则是为了约束接口,降低类对接口的依赖。

接口隔离原则是为了约束接口,降低类对接口的依赖。
接口隔离原则的优点:
1)灵活性,可维护性增强
2)高内聚,低耦合
3)减少代码冗余(减少了方法的实现)
4)体现对象层次

依赖倒置原则

依赖于抽象,而不是依赖于具体,依赖注入模式

依赖倒置原则(Dependency Inversion Principle,DIP)是面向对象设计中的一个原则,它是SOLID原则中的一部分。依赖倒置原则的核心思想是:

高层模块不应该依赖于低层模块,二者都应该依赖于抽象; 抽象不应该依赖于具体细节,而具体细节应该依赖于抽象。

(依赖于抽象)

简而言之,依赖倒置原则要求我们通过抽象来解耦高层模块和低层模块之间的依赖关系,从而使系统更加灵活、可扩展和易于维护。

核心思路: 要依赖于抽象 ,不要依赖于具体

为了实现这一原则 ,在编程时针对抽象类或者接口编程,而不是具体要求实现

九、设计模式

设计模式是一套反复被使用,经过验证的,代码的总结 ;

设计模式不是具体的方法,而一种思想.

学习设计模式就是要建立面向对象的思想,尽可能的面向接口编程,低耦合,高内聚,使程序实现复用

设计模式的几个要素

  1. 名字, 必须有一个简单,有意义的名称
  2. 问题 描述在何使用
  3. 解决方案 如何去解决问题
  4. 效果 模式优点缺点

设计模式分类:

创建型模式 对象的创建

结构型模式 对象的组成(结构)

行为型模式 对象的行为

创建型模式: 简单工厂模式, 工厂模式,单例模式等。。。

**结构型模式:**外观模式,适配器模式,装饰模式 。。。

**行为型模式:**模板方法模式,观察者模式,状态模式。。。

1.常见设计模式

简单工厂模式

静态工厂方法模式,它定义一个具体的工厂类负责创建一些类的实例

优点:客户端不需要负责创建对象,明确了各位类的职责

缺点:静态工厂负责创建对象,如果有新的对象增加,或者创建方式不同,需要不断的修改工厂类,不利于后期维护

public class AnimalFoctory {private AnimalFoctory(){}public static Animal createAnimal(String type){if("dog".equals(type)){return new Dog();}else if("cat".equals(type)){return new Cat();}else{return null;}}public static Dog createDog(){return  new Dog();}public static Cat createCat(){return  new Cat();}
}
工厂模式

工厂模式: 抽象工厂类负责定义创建对象的接口,具体对象的创建由继承抽象工厂的具体类实现

优点:客户端不需要负责创建对象,明确了各位类的职责 ; 如果 新的对象增加,不修改已有的代码,增加了维护性和扩展性

缺点:需要额外编写代码,增加了工作量

单例模式

单例模式: 确保类在内存中只有一个对象,此实例必须自动创建,并且对外提供

优点:

缺点:

(饿汉式): 类加载的就创建对象

public class Student {// 为了让静态方法可以访问此对象,所以把它变成静态的// 为了让外界不能直接访问,加privateprivate static Student s = new Student();private Student(){}public static Student getStudent(){return s;}
}

(懒汉式):用的时候,才去创建

public class Student2 {private static Student2 s = null;private Student2(){}public static Student2 getStudent(){if(s==null){s = new Student2();}return s;}
}

面试题:单例模式的思想是什么?请写一代码体现。

​ 开发:饿汉式(是不会出现问题的)

​ 面试:懒汉式(可能会出现问题的)

​ A: 懒加载(延迟加载)

​ B: 线程安全问题

public class Student2 {private static Student2 s = null;private Student2(){}public static synchronized Student2 getStudent(){if(s==null){s = new Student2();}return s;}
}
Runtime类
public class Runtime {private static Runtime currentRuntime = new Runtime();public static Runtime getRuntime() {return currentRuntime;}/** Don't let anyone else instantiate this class */private Runtime() {}}
模式设计模式

需求: 计算出一段代码的运行时间

优点: 满足用户需求,灵活多变

缺点:如果算法需要改变,需要修改抽象 类

装饰设计模式(扩展对象)

优点:

可以提供比继承更灵活的扩展对象的功能

缺点:可以任意组合

已经学过的装饰:

Scanner scanner = new Scanner(System.in);

2.枚举

枚举是指变量的一一列出来,只能在指范围内取值;

如: 一周只有7天,一年12个月

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

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

相关文章

深度探索Linux操作系统 —— 构建桌面环境

系列文章目录 深度探索Linux操作系统 —— 编译过程分析 深度探索Linux操作系统 —— 构建工具链 深度探索Linux操作系统 —— 构建内核 深度探索Linux操作系统 —— 构建initramfs 深度探索Linux操作系统 —— 从内核空间到用户空间 深度探索Linux操作系统 —— 构建根文件系统…

Quartus II + Modelsim 脚本仿真

软件版本&#xff1a;Intel Quartus Prime Design Suite: 23.2 方式参考附件Intel 官方文档&#xff1a;Questa*-Intel FPGA Edition Quick-Start: Intel Quartus Prime Pro Edition 第1步&#xff0c;创建一个ram ip&#xff0c;并形成一个例化的top层ip 第2步&#xff0c;自…

免费图片无损放大:8大平台突破画质极限

之前介绍过图片提高清晰度的工具平台&#xff0c;这次AIGCer介绍下将图片无损放大的几个在线免费的工具平台。图片高清放大是一种处理低分辨率图像的方法&#xff0c;以增加图像的尺寸和细节&#xff0c;使其看起来更大、更清晰。 1.美图设计室 传送门&#xff1a;https://ww…

基于Python+WaveNet+MFCC+Tensorflow智能方言分类—深度学习算法应用(含全部工程源码)(二)

目录 前言引言总体设计系统整体结构图系统流程图 运行环境模块实现1. 数据预处理1&#xff09;数据介绍2&#xff09;数据测试3&#xff09;数据处理 相关其它博客工程源代码下载其它资料下载 前言 博主前段时间发布了一篇有关方言识别和分类模型训练的博客&#xff0c;在读者…

什么是Z-Wave,技术特点,各国支持的频段

1.1 背景 Z-Wave是一种无线通信的协议&#xff0c;主要应用于智能家居网络&#xff0c;而其Z-Wave联盟主要是推动家庭自动化领域采用Z-Wave协议&#xff0c;其联盟成员都是智能家居领域非常有名的厂商&#xff0c;基本上覆盖了全球。 2.1 技术特点 低功耗、高可…

BigDecimald简单使用

为什么要用BigDecimal运算 在计算浮点型数据时,往往会存在数据计算失真问题 例1 2.0 - 1.9 应该等于0.1,用float类型赋值运算得出的结果为0.100000024,有问题 例2 1.8 - 1.9 应该等于 -0.1,用double类型赋值得出的结果为-0.09999999999999987,明显有问题 BigDecimal使用 BigDec…

用23种设计模式打造一个cocos creator的游戏框架----(十四)观察者模式

1、模式标准 模式名称&#xff1a;观察者模式 模式分类&#xff1a;行为型 模式意图&#xff1a;定义对象间的一种一对多的依赖关系&#xff0c;当一个对象的状态发生改变时&#xff0c;所有依赖于它的对象都得到通知并被自动更新。 结构图&#xff1a; 适用于&#xff1a;…

网神 SecGate 3600 防火墙 多处任意文件上传漏洞复现

0x01 产品简介 网神SecGate 3600防火墙是基于状态检测包过滤和应用级代理的复合型硬件防火墙,是专门面向大中型企业、政府、军队、高校等用户开发的新一代专业防火墙设备,支持外部攻击防范、内网安全、网络访问权限控制、网络流量监控和带宽管理、动态路由、网页内容过滤、邮…

【Jeecg Boot 3 - 第二天】1.2、jar 包和 lib 依赖分离,部署包缩小100倍

一、场景 二、思路 三、实战 ▶ 2.1、项目 jar 包解压获取 lib config Stage 1&#xff1a;正常打包获取 jeecg-system-start-3.6.0.jar Stage 2&#xff1a;解压 获取如下文件 Stage 3&#xff1a;获取 lib config ▶ 2.2、获取简化版项目jar包 Stage 1&#xff1…

AI+无代码助力企业供应链优化

内容来自演讲&#xff1a;潘峰 | 预见明日科技&#xff08;北京&#xff09;有限公司 | CEO 摘要 本文介绍了企业供应链中的挑战和解决方案。文章指出&#xff0c;供应链成本占企业经营成本的大部分&#xff0c;且存在供给端和需求端的高度不确定性。为应对这种不确定性&…

【深度学习】注意力机制(二)

本文介绍一些注意力机制的实现&#xff0c;包括EA/MHSA/SK/DA/EPSA。 【深度学习】注意力机制&#xff08;一&#xff09; 【深度学习】注意力机制&#xff08;三&#xff09; 目录 一、EA&#xff08;External Attention&#xff09; 二、Multi Head Self Attention 三、…

ActiveMQ任意文件写入漏洞(CVE-2016-3088)

简述&#xff1a;ActiveMQ的fileserver支持写入文件(但是不支持解析jsp),同时也支持移动文件。所以我们只需要先上传到服务器&#xff0c;然后再移动到可以解析的地方即可造成任意文件写入漏洞。我们可以利用这个漏洞来上传webshell或者上传定时任务文件。 漏洞复现 启动环境 …

stm32 HAL库 发送接受 到了一定的字符串后就卡在.s文件中

问题介绍&#xff1a; 某个项目开发过程中&#xff0c;串口接收中断&#xff0c;开启了DMA数据传输&#xff0c;开启了DMA中断&#xff0c;开启DMA半满中断。然后程序运行的过程中&#xff0c;接收了一部分数据后就会卡在启动文件的DMA1_Ch4_7_DMA2_Ch3_5_IRQHandler 中断里。…

Etcd实战(二)-k8s集群中Etcd数据存储

1 介绍 k8s中所有对象的manifest都需要保存到某个地方&#xff0c;这样他们的manifest在api server重启和失败的时候才不会丢失&#xff0c;因此引入了etcd。在k8s中只有api server和etcd直接交互&#xff0c;其它组件都通过api server间接和etcd交互&#xff0c;这样做的好处…

Flink反压如何查看和优化

我们在使用Flink程序进行流式数据处理时&#xff0c;由于种种原因难免会遇到性能问题&#xff0c;如我们在使用Flink程序消费kafka数据&#xff0c;可能会遇到kafka数据有堆积的情况&#xff0c;并且随着时间的推移&#xff0c;数据堆积越来越多&#xff0c;这就表名消费处理数…

机器学习---Boosting

1. Boosting算法 Boosting思想源于三个臭皮匠&#xff0c;胜过诸葛亮。找到许多粗略的经验法则比找到一个单一的、高度预 测的规则要容易得多&#xff0c;也更有效。 预测明天是晴是雨&#xff1f;传统观念&#xff1a;依赖于专家系统&#xff08;A perfect Expert) 以“人无…

云基础软件深化合作,云轴科技ZStack与麒麟软件战略签约

12月8日&#xff0c;云轴科技ZStack与麒麟软件战略合作签约仪式在北京举行&#xff0c;双方对过往紧密合作表达了充分肯定&#xff0c;并就进一步联合技术创新、打造重点行业标杆和持续赋能客户达成高度共识。云轴科技创始人&CEO张鑫和麒麟软件高级副总经理谢文征共同见证双…

Oracle(2-17) RMAN Maintenance

文章目录 一、基础知识1、Retention Policy 保留政策2、Recovery Window - Part 1 恢复窗口-第1部分3、Cross Checking 交叉检查4、The CROSSCHECK Command CROSSCHECK命令5、OBSOLETE VS EXPIRED 过时与过期6、Deleting Backups and Copies 删除备份和副本7、The DELETE Comma…

无参RCE [GXYCTF2019]禁止套娃1

打开题目 毫无思绪&#xff0c;先用御剑扫描一下 只能扫出index.php 我们尝试能不能用php伪协议读取flag php://filter/readconvert.base64-encode/resourceindex.php php://filter/readconvert.base64-encode/resourceflag.php 但是页面都回显了429 怀疑是不是源码泄露 用…

【Linux学习】深入理解动态库与静态库

目录 十三.动态库与静态库 13.1 认识动静态库 13.2 深入理解动静态库 什么是库? 编译链接过程 动静态库的基本原理 13.3 静态库 静态库的打包: 静态库的使用: 13.4 动态库 动态库的打包: 动态库的使用: 13.5 动态库与静态库怎么选? 十三.动态库与静态库 13.1 认识动静态库 …