XML标签语句
- XML
- 概念: Extensible Markup Language, 可扩展标记语言. 是一种标记语言, 类似于HTML. 是W3C组织发布的, 目前XML的规范是W3C于2000年发布的XML1.0规范
- 作用: 用于描述数据, 而非显示数据. 擅长表示包含嵌套的数据关系(一对多关系)
- 注意: XML没有预定义的标签, 所有标签都需要用户定义
- 应用场景:
- XML文档的组成部分
- 文档声明
- 必须在XML文档第一行
- 属性
- version: XML版本, 目前1.0
- encoding: XML文件编码, 文件编码必须和声明编码一致. 默认UTF-8
- standalone: 文档是否独立不依赖于其他文档. 默认no
- 元素
- 组成部分
- 标签种类
- 闭合标签: <name></name>
- 有标签体: <name>Bill Gates</name>
- 无标签体: <name></name>
- 自闭合标签: <name value="Bill Gates" />
- 标签名命名规范
- 可以包含字母, 数字, 减号, 下划线, 英文句点
- 区分大小写:
和 是不一样的 - 只能以字母或下划线开头: , <_ab12>
- 不能以xml, XML, Xml等开头, 这个词属于保留词
- 名称字符之间不能有空格或制表符
- 名称字符之间不能使用冒号:, 这个冒号有特殊用途
- 标签的嵌套
- XML文档有且只有一个根标签
- 元素的属性
- 在开始标签内, 以键值对形式表示该标签的属性
- 属性名的命名规范与标签名相同
- 属性值必须使用引号引起来, 可以使用单引号'或双引号"
- 一个标签可以有多个属性, 属性名不能重复
- 标签的属性可以改用子标签来定义
- 注释
- 格式: <!-- 注释内容 -->, 适用于单行和多行
- 注意:
- 注释不会被当做标签解析
- 注释不能嵌套
- XML声明之前不能有注释
- 原因: 只有先解析到XML声明才知道该文档是一个XML文档, 才会把<!-- -->当做注释.
- CDATA区
- 格式: <![CDATA[你的内容]]>
- 作用: CDATA区中的内容只会被当做普通字符串解析, 即使有标签也不会被解析
- 特殊字符
- &: &
- <: <
- >: >
- ": "
- ': '
- 处理指令
- PI, Processing Instruction
- 作用: 指示软件如何解析XML文档
- 语法: 必须以<?开头, 以?>结尾
- 常用处理指令
- XML声明: <?xml version="1.0" encoding="UTF-8" ?>
- XML-Stylesheet指令:<?xml-stylesheet type="text/css" href="some.css" ?>
- XML约束
- 约束的作用: 用于约束文档中使用的书写规范(即能使用哪些标签, 属性, 属性值, 标签的顺序, 次数等)
- 为什么要使用约束: 由于XML标签都是自定义标签, 所以标签和属性是否正确需要通过约束来进行检查
- DTD约束
- 概念: Document Type Defination, 文档类型定义.
- dtd文件规范:
- 以.dtd后缀结尾
- 需要XML文档声明, 文件编码必须为UTF-8
- DTD约束的定义
- ELEMENT: <!ELEMENT 标签名称 使用规则>
- 声明一个XML标签
- 使用规则
- (#PCDATA): Parsed Character Data, 指示元素的主题内容只能是普通的文本
- EMPTY: 指示元素的主体为空, 如<br/>
- ANY: 指示元素的主题内容为任意类型
- (子元素): 指示元素中包含的子元素
- 子元素用逗号,分隔: 则必须按声明顺序编写XML元素
- 子元素用竖线|分隔: 任选其一即可
- 子元素后什么都没有: 必须且只能出现一次
- 子元素用+分隔: 至少出现一次
- 子元素用*分隔: 出现零次或任意次
- 子元素用?分隔: 出现零次或一次
- ATTLIST: <!ATTLIST 元素名 属性名 属性值类型 设置说明 ...>
- 声明一个标签的属性
- 属性值类型
- CDATA: 属性的取值为普通的文本字符串
- ENUMERATED: 枚举, 从列表中任选其一
- ID: 属性的取值不能重复
- 设置说明
- #REQUIRED: 该属性必须出现
- #IMPLIED: 表示该属性可有可无
- #FIXED="固定值": 表示属性的取值为一个固定值
- 值: 表示属性的取值的默认值为该值
- DTD约束文件的引入
- 引入本地约束文件: <!DOCTYPE 根标签名 SYSTEM "dtd文档路径">
- 引入网络约束文件: <!DOCTYPE 根元素 PUBLIC "dtd名称" "DTD文档的URL">
- Schema约束
- 用于取代DTD
- Schema相较于DTD的优势
- Schema更符合XML语法结构
- DOM, SAX等XML解析库更容易解析Schema文档
- Schema对命名空间支持很好
- Schema比DTD支持更多的数据类型, 并支持用户自定义新的数据类型
- Schema定义约束的能力非常强大, 可以对XML实例文档做出细致的语言限制
- Schema要求
- Schema本身是一个XML文件, 但后缀名为.xsd
- Schema文档通常被称为模式文档(约束文档), 遵循该文档的XML文件称为实例文档
- Schema文档必须有一个根节点, 且该根节点名称必须为<schema>
- 编写了一个Schema约束文档后, 需要把这个约束文档中声明的元素绑定到一个URI地址上. 这一过程叫做将元素绑定到一个命名空间, 以后XML文件就可以通过这个URI找到约束文档
- Schema约束文件的定义
- 定义命名空间的URI
- targetNamespace='http://www.baidu.com': 声明命名空间要绑定的URI. 当XML文件引用该约束文档时, 只需要引用该URI即可找到约束文档
- 定义标签约束
- <xs:element name='标签名'>: 定义一个标签
- name属性: 定义标签名
- type属性: 定义属性值类型
- <xs:complexType>: 声明一个复杂类型标签, 即可以有子标签
- <xs:sequence>: 约束子标签的定义顺序
- Schema约束文件的引用
- 引用网络约束文件:
- 方式1: xmlns:xs='http://www.w3.org/2001/XMLSchema'
- 声明一个命名空间, 并且给这个命名空间起一个别名xs, 当使用该命名空间的标签时, 使用xs:标签来使用
- 方式2: xmlns='http://www.w3.org/2001/XMLSchema'
- 声明一个命名空间, 没有别名, 所以在使用该命名空间的标签时, 不用加前缀. 这种方式容易造成标签名冲突
- 引用本地约束文件
- 除了使用以上2种方式, 还要增加xsi:schemaLocation="命名空间URI 约束文件路径": 将命名空间URI和约束文档路径对应起来(一般用于本地schema约束).
- 标签前缀: xs:标签, xs就是前缀
- QName: xs:标签, 整体叫做QName, Qualified Name
- 解析XML
- DOM解析
- DOM: Document Object Model, 文档对象模型. 是W3C推荐的处理XML的方式
- 解析原理: 基于树形模型原理. 无论要解析哪个节点, 先一次性将XML文档全部加载到内存中, 形成DOM树, 然后进行解析操作
- 好处: 文档加载完整, 操作节点简单
- 缺点: 消耗内存大
- SAX解析
- SAX: Simple API for XML, 第三方开源解析器
- 解析原理: 基于事件驱动原理. 从上往下读取XML文档, 当读取到要解析的节点的开始标签时触发一个事件, 开始从这里加载到内存, 当读取到要解析节点的结束标签时, 触发一个事件, 结束加载. 从而只会得到要解析的节点部分
- 好处: 节省内存
- 缺点: 文档加载不完整, 如果要进行增删改节点, 要反复多次读取文档, 效率低
- 第三方解析库:
- JAXP: Java提供的解析XML规范, 规定了Dom和SAX两种解析方式
- Dom4J: 第三方开源Dom解析库(使用方便, 推荐), 同时支持DOM解析和SAX两种解析方式, 也实现了JAXP
- org.dom4j.io.SAXReader类: SAX解析器
- 构造方法:
- 成员方法:
- Document read(String systemId): 读取XML文件, 返回一个Document对象
- org.dom4j.io.OutputFormat类: 配置XML输出格式
- static OutputFormat createPrettyPrint(): 创建一个用户输出美观格式的OutputFormat对象
- void setEncoding(String encoding): 设置字符集
- org.dom4j.io.XMLWriter类: 用于向XML中写入数据的输出流
- 构造方法:
- XMLWriter(OutputStream out): 使用字节流创建一个XMLWriter对象
- 成员方法:
- void write(Document doc): 将Document对象中的数据写入到XML文件
- org.dom4j.Document接口: 代表一个XML文档
- Element getRootElement(): 获取根元素对象. 需要用根元素获取其他子元素
- org.dom4j.Element接口: 代表一个元素
- 获取元素信息
- 元素增删改查
- 获取元素
- List<Element> elements(): 获取调用元素对象的所有子元素
- List<Element> elements(String name): 获取所有的指定名称的子元素
- Element element(String name): 获取第一个该名称的子元素对象
- Element getParent(): 获取当前元素的父元素对象
- 添加元素
- Element addElement(String elementName): 在当前元素下添加指定名称的子元素
- 删除元素
- boolean remove(Element child): 删除子元素
- 操作元素中的文本
- String elementText(String name): 获取第一个该名称的子元素的文本内容
- String getText(): 获取当前元素对象的文本
- void setText(String text): 设置当前元素对象的文本
- 操作元素的属性
- String attributeValue(String name): 根据指定的属性名获取属性值
- Element addAttribute(String name, String value): 添加或修改指定属性名的属性值
- org.dom4j.DocumentHelper类:
- static Element createElement(String name): 使用指定名称作为元素名, 创建一个元素对象
- 注意:
- 要删除一个节点, 必须通过其父节点来删除
- 在内存中对Document进行修改后, 需要写回文档
MySQL数据库
- 数据库
- 概念: 存储数据的仓库. 本质是一个文件系统, 数据按照指定的格式将数据存储起来, 用户可以对数据库中的数据进行增删改查
- DBMS: Database Management System, 数据库管理系统. 是操作和管理数据库的大型软件, 用于建立, 使用和维护数据库, 对数据库进行统一管理和控制, 以保证数据库的安全性和完整性. 用户通过数据库管理系统访问数据库中表内的数据
- 常见数据库
- 数据库: 存储数据表
- 数据表: 存储记录
- DBMS: 操作数据库
- 表和Java类的对应关系
- 表名: Java类名
- 列名: 成员属性名
- 记录: 类对象
- MySQL
- 安装
- 配置和遇到的问题
- 命令行的登录和退出
- 登录: mysql -u 用户名 -p
- 退出: exit
- SQL基本语言
- SQL的概念: Structured Query Language, 结构化查询语言
- 结构: 数据表是由行和列组成的, 是有结构的, 从这种结构中查询
- SQL的4中分类
- DDL: Data Defination Language, 数据定义语言, 用来定义数据库对象(库, 表等)
- DML: Data Manipulation Language, 数据操作语言, 对表中的记录进行增, 删, 改
- DQL: Data Query Language, 数据查询语言, 对表中的记录进行查
- DCL: Data Control Language, 数据控制语言, 创建修改用户, 权限
- SQL特点
- SQL不区分大小写
- 一条SQL语句以;分号结尾, 一条语句可以多行书写
- 单词之间通过空格分隔, 参数之间通过,逗号分隔
- 字符串和日期要用''或""引起来, 建议单引号
- SQL注释(2+1种)
- SQL的数据类型
- INT: 整数
- DOUBLE: 小数
- VARCHAR: 可变长度字符
- CHAR: 固定长度字符
- 其他看文档
- VARCHAR和CHAR的区别:
- VARCHAR(200), 可变长度字符, 存储占用的内存空间是可变的, 如果你的数据容量小于我们指定的空间大小, 那么就会按照实际的数据空间来开辟内存大小
- 优点: 节省内存
- 缺点: 因为每次存入数据时都会判断数据的实际大小, 来动态修改内存空间, 所以需要占用资源, 效率低
- CHAR(200), 固定长度字符, 存储占用的内存空间是不可变的. 无论实际存入的数据容量是多大, 都占用这么大的空间
- 优点: 插入数据时不需要额外操作, 效率高
- 缺点: 可能会浪费空间
- SQL对库的操作
- 创建库
- 使用默认字符集创建库: CREATE DATABASE 库名;
- 指定字符集: CREATE DATABASE 库名 CHARACTER SET '字符集';
- 删除库
- 查看所有库
- 使用库
- 查看当前使用的库
- SQL对表的操作
- 创建表: CREATE TABLE 表名 (列名1 数据类型 约束, 列名2 数据类型 约束);
- 删除表: DROP TABLE 表名;
- 查看当前库中的所有表: SHOW TABLES;
- 修改表的结构: ALTER TABLE 表名 操作关键字 列名 数据类型 约束;
- 增加列: ALTER TABLE 表名 ADD 新列名 新数据类型 新约束;
- 删除列: ALTER TABLE 表名 DROP 列名;
- 修改列的数据类型和约束(不能修改列名):ALTER TABLE 表名 MODIFY 列名 新数据类型 新约束;
- 修改列的列名, 数据类型, 约束:ALTER TABLE 表名 CHANGE 旧列名 新列名 新数据类型 新约束;
- 修改表名: RENAME TABLE 旧表名 TO 新表名;
- SQL对记录的操作
- 增
- 一次插入一条记录: INSERT INTO 表名 (列1, 列2) VALUES (值1, 值2);
- 一次性插入一条记录(省略自增主键):INSERT INTO 表名 (非主键自增列1, 非主键自增列2) VALUES (值1, 值2);
- 一次插入所有列的记录(省略列名): INSERT INTO 表名 VALUES (值1, 值2);
- 一次插入多个记录(指定列):INSERT INTO 表名 (列1, 列2) VALUES (记录1值1, 记录1值2), (记录2值1, 记录2值2);
- 一次插入多个记录(省略列):INSERT INTO 表名 VALUES (记录1值1, 记录1值2), (记录2值1, 记录2值2);
- 删
- 删除符合条件的记录: DELETE FROM 表名 WHERE 条件;
- 删除所有记录: DELETE FROM 表名;
- 清空表: TRUNCATE TABLE 表名;
- DELETE FROM 表名;和TRUNCATE TABLE 表名;的区别
- DELETE, 逐条删除记录, 不会重置自增计数器
- TRUNCATE, 删除表再重建, 会重置自增计数器
- 改
- 修改符合条件的记录: UPDATE 表名 SET 列名1=新值, 列名2=新值 WHERE 条件;
- 修改所有记录: UPDATE 表名 SET 列名1=新值, 列名2=新值;
- 查
- 查询指定列: SELECT 列名1, 列名2 FROM 表名;
- 查询所有列: SELECT * FROM 表名;
- 条件查询: SELECT 列名1, 列名2 FROM 表名 WHERE 条件;
- 运算符
- 比较运算符
- =: 相等
- <>或!=: 不等
- >: 大于
- <: 小于
- >=: 大于等于
- <=: 小于等于
- BETWEEN...AND...: 在一个范围内(包含头和尾)
- IN (): 在列表中, 满足列表中一个即可
- IS NULL: 是空
- LIKE '通配符': 模糊查询
- %: 一个百分号可以表示任意个字符. 比如'王%', 王大锤, 王五
- _: 一个下划线可以表示一个字符. 比如'王_', 只能匹配王五
- 逻辑运算符
- AND: 与. 两边条件同时成立才成立
- OR: 或. 两边条件只要有一个成立就成立
- NOT: 非, 取相反结果
- NOT BETWEEN ... AND ...: 不在范围内
- NOT IN: 不在列表中
- NOT LIKE: 不匹配
- IS NOT NULL: 非空
- 去重: SELECT DICTINCT 列名1, 列名2 ... FROM 表名 WHERE 条件;
- 别名:
- 高级SQL
- 排序
- ORDER BY 列名 ASC|DESC;
- 注意:
- 默认顺序为升序ASC
- WHERE在前, ORDER BY在后
- 聚合函数
- 用在SELECT后或HAVING后
- COUNT(列名): 计算记录数量
- SUM(列名): 将该列的值求总和
- MAX(列名): 求该列值中的最大值
- MIN(列名): 求该列值中的最小值
- AVG(列名): 求该列所有值的平均值
- 分组
- GROUP BY 列名 HAVING 条件;: 对查询结果集分组, 然后再按条件过滤
- 注意:
- 聚合函数与分组的使用效果
- 使用聚合函数后再进行分组, 才相当于汇总统计
- SELECT zname, SUM(zmoney) FROM zhangwu GROUP BY zname;
- 不使用聚合函数的分组, 只有第一条记录的值
- SELECT zname, zmoney FROM zhangwu GROUP BY zname;
- HAVING和WHERE的区别
- 过滤时机不同
- WHERE是在分组前先对查询结果进行过滤
- HAVING是在查询结果分组后再次过滤
- 是否可跟随聚合函数不同
- WHERE条件中不可使用聚合函数
- HAVING条件中可以使用聚合函数
- 条件可用列名不同
- HAVING条件中的列名必须是SELECT或GROUP BY中使用过的列名
- WHERE条件中可以使用表的所有列名
JDBC
- JDBC: Java数据库连接. SUN公司提供的接口, 用来让数据库厂商实现数据库操作的功能
- 数据库驱动: 就是JDBC的实现
- JDBC开发步骤:
- 前提: 导包(数据库驱动)
- 步骤:
- 注册驱动
- DriverManager.registerDriver(): 是真实的注册驱动的方法
- 因为驱动中实现了这个方法, 推荐我们使用:
- Class.forName("数据库驱动的Driver实现类全类名")
- 获取连接:
- Connection conn = DriverManager.getConnection(url, username, password)
- 获取执行平台:
- Statement s = conn.createStatement();: 不安全的
- PreparedStatement ps = conn.prepareStatement(String sql);: 可以防范SQL注入
- 设置参数:
- 占位符: ?, 即使是字符串, 也不要给问号加引号
- void setObject(int index, Object obj)
- 执行SQL语句
- Statement
- 增删改: int s.executeUpdate(String sql)
- 判断操作是否成功: 判断返回值是否>0则生效, 否则不成功
- 查: ResultSet rs = s.executeQuery(String sql)
- 思考: 判断操作是否成功: 是返回null呢还是调用.next()用是否为true判断?
- PreparedStatement
- 增删改: int ps.executeUpdate();
- 判断操作是否成功: 判断返回值是否>0则生效, 否则不成功
- 查: ResultSet rs = ps.executeQuery();
- 处理结果
- ResultSet
- boolean next();: 将指针向后移动, 如果有下一个记录则true, 否则false
- 默认不执行的之后, 指针在第一条记录之前; 只有调用一次才能指向第一条: while (rs.next()) {}
- String getString(String 列名): 获取指定列的值, 以String类型
- Object getObject(String 列名): 获取指定列的值, 以Object类型
- 释放资源
- resultSet.close()
- preparedStatement.close()
- statement.close()
- connection.close()
- SQL注入
- 原理: 拼接SQL导致用户的输入可以改变SQL的意义, Statement无法避免注入
- 超级密码: 1' OR '1=1
- 如何避免: 使用PreparedStatement替换Statement
- JDBCUtils工具类的自定义
- 在静态代码块中初始化连接对象
- 定义方法获取连接对象, 释放资源
- 使用Properties配置文件
- 作用: 将配置信息从源代码中隔离, 达到可以直接修改配置文件, 而不用修改源代码的目的
- 配置文件的创建
- 在src目录下创建, 会自动在bin目录下生成
- 以.properties后缀结尾
- 配置文件的格式: 键值对, 一行一个键值对
- 读取配置文件
- 通过类加载器, 去加载bin目录下的配置文件
- 类加载器的获取:
- 获取类的字节码对象: 类名.class
- 通过类的字节码对象获取类加载器: ClassLoader 字节码对象.getClassLoader()
- 通过类加载器对象读取资源文件:InputStream getResourceAsStream(String 配置文件路径)
- 创建Properties对象: Properties p = new Properties();
- 通过该对象加载流(此时Properties对象才有数据): p.load(inputStream)
- 通过Properties对象获取属性值: String p.getProperty(String key)
- DbUtils
- 是什么: 是Apache的Commons项目中的一个组件, 开源的工具类(第三方库)
- 三个核心类/接口
- QueryRunner类: 提供操作SQL语句的API
- QueryRunner(): 创建对象
- int update(Connection conn, String sql, Object... param): 执行INSERT, DELETE, UPDATE语句, 同时传入占位符的参数值, 是可变参数
- <T> T query(Connection conn, String sql, ResultSetHandler<T> rsh, Object... params): 执行SELECT查询, 并根据传入的结果集处理器来处理结果
- ResultSetHandler接口: 定义SELECT操作后对结果集的操作方法, 可以将结果集转换为Java类
- ArrayHandler类: 将结果集的第一条记录封装到一个Object[]数组中, 数组中的每一个元素就是该条记录中的每一列的值
- ArrayListHandler类: 将结果集中的每一条记录都封装到一个Object[]数组中, 再将这些数组封装到List<Object[]>集合中
- BeanHandler类: 将结果集中的第一条记录封装到一个指定的JavaBean中
- BeanListHandler类: 将结果集中的每一条记录都封装到一个指定的JavaBean中, 再将这些JavaBean封装到List<T>集合中
- ColumnListHandler类: 将结果集中指定的列的字段值, 封装到一个List集合. 用于竖向查一个列
- ScalarHandler类: 获取单一结果, 用于聚合函数如SELECT COUNT(*) FROM 表的操作
- MapHandler类: 将结果集的第一条记录封装到一个Map中. key是列名, value是第一条记录的每个字段的值
- MapListHandler类: 将结果集的每一条记录封装到一个Map中. key是列名, value是第一条记录的每个字段的值. 然后再将这些Map封装到一个List中
- DbUtils类: 用于关闭资源和事务处理
- static void closeQuietly(Connection conn): 关闭连接, 内部处理了异常
```java /* JDBC工具类: v2.0 可以读取配置文件 */ public class JDBCUtilsConfig { // 声明静态变量private static Connection connection;private static String driverClass;private static String url;private static String username;private static String password;// 静态代码块进行初始化static { try { // 读取配置文件 readConfig(); // 注册驱动 Class.forName(driverClass); // 获取连接 connection = DriverManager.getConnection(url, username, password); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("数据库连接失败"); }}// 私有构造方法private JDBCUtilsConfig() {}// 读取配置文件方法private static void readConfig() throws Exception { // 使用类加载器加载bin目录下的配置文件, 获取输入流 InputStream in = JDBCUtilsConfig.class.getClassLoader().getResourceAsStream("database.properties"); // 创建Properties对象 Properties properties = new Properties(); // 加载数据 properties.load(in); // 通过键获取值 driverClass = properties.getProperty("driverClass"); url = properties.getProperty("url"); username = properties.getProperty("username"); password = properties.getProperty("password");}// 获取连接对象public static Connection getConnection() { return connection;}} - DBCP连接池
- Apache commons项目中的一个组件
- 作用: 提供连接池, 替代连接. 连接池可以存放多个连接, 反复使用, 而不用每次创建销毁, 提高效率, 节省资源
- 普通连接的弊端: 获取连接, 释放资源太消耗资源.
- Sun公司提供了接口: javax.sql.DataSource接口: 连接池规范
- 连接池的实现:
- DBCP
- 导包
- commons-dbcp-x.x.jar
- commons-pool-x.x.x.jar
- BasicDataSource: 是DataSource接口的实现类
- 必选
- BasicDataSource BasicDataSource(): 创建对象
- void setDriverClassName(String name): 设置驱动类名
- void setUrl(String url): 设置连接地址
- void setUsername(String username): 设置用户名
- void setPassword(String password): 设置密码
- Connection getConnection(): 获取连接对象
- 可选
- void setMaxActive(int n): 最大连接数量. 程序能够连接数据库的最大连接数量
- void setMinIdle(int n): 最小空闲连接. 连接池中允许存在的最小空闲数量, 如果小于该数量, 则会创建新的连接, 直到满足该最小空闲连接数
- void setMaxIdle(int n): 最大空闲连接. 连接池中允许存在的最大空闲数量, 如果超出该数量, 则超出的空闲连接会被真实关闭
- void setInitialSize(int size): 初始化连接数. 连接池中最初的连接数
- 改写JDBCUtils
- 将注册驱动, 获取连接的代码修改为必选4项
- 将getConnection()方法替换为getDataSource()方法
- 用户登录注册案例
- 理解如何分析需求, 将其转换为不同的步骤
- 注册:
- 先检查用户名是否存在(SELECT)
- 如果存在: 注册失败, 提示更换用户名
- 如果不存在: 直接注册(INSERT INTO)
- 登录
- 查询用户表中是否有匹配的用户名和密码(SELECT)
- 如果存在: 用户已经注册且密码匹配, 登录成功
- 如果用户名不存在: 用户没有注册或, 登录失败
- 如果用户名存在, 密码不匹配: 登录失败
- dao: 操作数据库的类
设计模式
- 什么是设计模式
- 对问题处理方式的总结经验, 形成了一种代码设计的模式, 按这种模式不会再出问题, 所以叫做设计模式
- 所有的设计模式都源于面向对象的思想
- Java有23种设计模式
单例模式: 饿汉式- 单例:
- 单一实例, single instance, singleton, 目的是保证这个类只存在一个唯一的对象
- 为什么叫饿汉式:
- 因为类一加载, 对象就已经创建了, 像一个饿汉见到吃的马上就吃
3个要点 - 把构造方法私有化
- 在类中定义一个静态的本类对象, 并且要初始化
- 提供一个静态的方法getInstance(), 获取单例对象
单例模式: 懒汉式```java /* 单例: 线程不安全的懒汉式 *
解决懒汉式单例的线程安全问题解决线程安全问题的方式 - 在if判断null外加上synchronize同步代码块解决
- 这样产生了一个副作用: 如果已经创建了对象, 下一个线程调用就没必要再去synchronize外面等待锁了. 否则影响程序的执行速度
- 应该直接判断对象是否为空, 不为空就直接return对象. 所以在synchronize外再套一层判断null
简单工厂设计模式- 用于解决创建对象的问题
- 我们以前在创建对象时, 需要根据每个类的构造方法创建对象
``` 简单工厂, 用一个工厂类, 根据传入不同的参数, 生产不同的对象
工厂方法设计模式- 工厂方法思想: 将每个对象交给各自的工厂去创建
- 动物有自己的继承体系
- 工厂也有自己的集成体系
- 猫, 狗都有各自的工厂
- 与简单工厂区别
- 工厂抽象为接口, 有各自工厂实现类
- 使用工厂的多态创建工厂, 使用动物的多态调用动物的方法
- 有什么用?
- 以后可能会用到第三方SDK, 他们会实现某种逻辑(比如QQ登录), 腾讯把登录逻辑都写好了, 用多态的抽象类或接口对象去创建对象, 调用方法, 但具体实现每个公司都不一样, 所以搞成接口或抽象类, 你需要自己定义类继承或实现, 重写方法. 腾讯就能调用了, 从而实现QQ登录
``` 工厂方法, 创建工厂接口, 定义创建不同对象的子工厂, 按照各自创建对象的方式重写工厂接口的方法 +-----------------------+| interface Factory || || Animal createAnimal() |+-----------------------+ | | +----------------+ | | CatFactory |__ +------| ___cat___cat__cat__cat____ | | createAnimal() | | +----------------+ | | +----------------+ | | DogFactory |__ +------| ____dog_ dog__dog__dog____ | createAnimal() | +----------------+集团化大企业, 不同分厂生产不同的产品, 由总部统一管理 ```
|
|