• Java进阶(十五)XML、XML解析、设计模式


    十五、XML、XML解析、设计模式

    需要学会什么?

    • XML:在有些业务场景下,存储数据或者传输数据给别人的时候,数据需要满足一定的规范进行组织。
    • XML解析技术:XML文件中存储的数据是需要提取出来的。
    • XPath:如何方便的在XML文件中进行数据的检索?
    • 设计模式:开发中还有一些比较常见的设计模式是需要掌握,理解设计模式有利于理解某些程序。

    1.XML

    a.XML概述

    XML概述:

    • XML是可扩展标记语言(eXtensible Markup Language)的缩写,它是一种数据表示格式,可以藐视非常复杂的数据结构,常用于传输和存储数据。

      
      <note>
          <to>Toveto>
          <from>Janifrom>
          <heading>Reminderheading>
          <body>Don't forget me this weekend!body>
      note>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7

    XML的几个特点和使用场景:

    • 纯文本,默认使用UTF-8编码。
    • 可嵌套。
    • 如果把XML内容存为文件,那么它就是一个XML文件。
    • XML的使用场景:XML内容经常被当成消息进行网络传输,或者作为配置文件用于存储系统的信息

    总结:

    1. XML是什么?
      • XML全称为(eXtensible Markup Language),是一种可扩展的标记语言。
      • XML是一种数据表示格式,可以用于自定义数据格式。
    2. XML的作用是什么?
      • 用于进行存储数据和传输数据。
      • 作为软件的配置文件。

    b.XML的创建、语法规则

    XML的创建:

    • 创建一个XML类型的文件,要求文件的后缀必须使用XML,如:hello_world.xml。

    XML的语法规则:

    • XML文件的后缀名为:xml

    • 文档声明必须是第一行。

      
      
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6

    XML的标签(元素)规则:

    • 标签由一对尖括号和合法标识符组成:必须存一个根标签,有且只能有一个。

    • 标签必须成对出现,又开始和结束:

    • 特殊的标签可以不成对,但是必须有结束标记,如:

    • 标签中可以定义属性,属性和标签名空格隔开,属性值必须用引号引起来

    • 标签需要正确的嵌套。

      
      <student>
          <name>花千骨name>
          <sex>sex>
          <hobby>修仙hobby>
          <info>
              <address>花莲村address>
              <age>16age>
          info>
      student>
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11

    XML的其他组成:

    • XML文件中可以定义注释信息:

      
      
      • 1
    • XML文件中可以存在以下特殊字符:

      < < 小于
      > > 大于
      & & 和号
      ' ' 单引号
      " " 双引号
      
      • 1
      • 2
      • 3
      • 4
      • 5
    • XML文件中可以存在CDATA区:

          
      
      • 1
      • 2
      • 3
    
    <student>
        <name>花千骨name>
        <sex>sex>
        <hobby>修仙hobby>
        <info>
            <address>花莲村address>
            <age>16age>
        info>
        
        
        
        <sql>
            select * from user where age < 18;
        sql>
    student>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    c.XML文档约束方法一:DTD约束

    什么是文档约束?

    • 用来限定XML文件中的标签以及属性应该怎么写。

    文档约束的分类:

    • DTD
    • schema

    案例:XML文档约束-DTD的使用。

    需求:

    • 利用DTD文档约束,约束一个XML文件的编写。

    分析:

    1. 编写DTD约束文档,后缀必须是.dtd。

      
      
      
      
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
    2. 在需要编写的XML文件中导入该DTD约束文档。

    3. 按照约束的规定编写XML文件的内容。

    data.dtd

    
    
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    hello_world_dtd.xml

    
    DOCTYPE 书架 SYSTEM "data.dtd">
    <书架>
        <>
            <书名>一往无前书名>
            <作者>范海涛作者>
            <售价>78售价>
        >
    书架>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    总结:

    1. XML的文档约束-DTD的作用和问题?
      • 可以约束XML文件的编写。
      • 不能约束具体的数据类型。

    d.XML文档约束方式二:schema约束

    文档约束-schema:

    • schema可以约束具体的数据类型,约束能力上更强大。
    • schema本身也是一个XML文件,本身也收到其他约束文件的要求,所以编写的更加严谨。
    约束
    约束
    其他文件
    schema
    XML

    案例:XML文档约束-schema的使用。

    需求:

    • 利用schema文档约束,约束一个XML文件的编写。

    分析:

    1. 编写schema约束文档,后缀必须是.xsd,具体的形式到代码中观看。
    2. 在需要编写的XML文件中导入该scheam约束文档。
    3. 按照约束内容编写XML文件的标签。

    data.xsd

    
    
        
        
            
            
                
                    
                    
                        
                            
                                
                                
                                
                            
                        
                    
                
            
        
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    hello_world_schema.xml

    
    <书架 xmlns="http://www.javase.cn">
        <>
            <书名>一往无前书名>
            <作者>范海涛作者>
            <售价>78售价>
        >
    书架>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    总结:

    1. XML的文档约束-schema的优点?
      • 可以约束XML文件的标签内容格式,以及具体的数据类型。

    2.XML解析技术

    a.XML解析技术概述

    XML的数据的作用是什么?最终需要怎么处理?

    • 存储数据、做配置i信息、进行数据传输。
    • 最终需要被程序进行读取,解析里面的信息。

    什么是XML解析?

    • 使用程序读取XML中的数据。
    • 两种解析方式:
      • SAX解析。
      • DOM解析。

    DOM常见的解析工具:

    名称说明
    JAXPSUM公司提供的一套XML的解析API。
    JDOMJDOM是一个开源项目,它基于树型结构,利用纯JAVA的技术对XML文档实现解析、生成、序列化以及多种操作。
    dom4j是JDOM的升级品,用来读写XML文件的。具有性能优异、功能强大和极易使用的特点,它得到性能超过SUN公司官方的DOM技术,同时它也是一个开源代码的软件,Hibernate也用它来读写配置文件。
    jsoup功能强大DOM方式的XML解析开发包,尤其对HTML解析更加方便。

    DOM解析文档对象模型:

    
    <students>
        
        <student id="1">
            <name>花千骨name>
            <age>16age>
        student>
        
        
        <student id="2">
            <name>轻水name>
            <age>17age>
        student>
        
    students>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    1
    2
    16
    17
    Document
    students
    student
    student
    id
    name
    age
    花千骨
    id
    name
    age
    轻水
    • Document对象:整个XML文档。
    • Node对象:
      • Element对象:标签。
      • Attribute对象:属性。
      • Text对象:文本内容。

    b.dom4j解析XML文件

    dom4j解析XML得到Document对象:

    SAXReader类:

    构造器/方法说明
    public SAXReader()创建Dom4J的解析器对象。
    Document read(String url)加载XML文档成为Document对象。

    Document类:

    方法名说明
    Element getRootElement()获取根元素对象。

    使用dom4j解析出XML文件。

    需求:

    • 使用dom4j把一个XML文件的数据进行解析。

    分析:

    1. 下载dom4j框架,https://dom4j.github.io/
    2. 在项目中创建一个文件夹:lib
    3. 将dom4j-x.x.x.jar文件复制到lib文件夹。
    4. 在IDEA中在jar文件上右键,选择Add as LIbrary,点击OK。
    5. 在类中导包使用。

    students.xml

    
    <students>
        
        <student id="1">
            <name>花千骨name>
            <age>16age>
        student>
    
        
        <student id="2">
            <name>轻水name>
            <age>17age>
        student>
    
    students>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    Dom4jDemo.java

    import org.dom4j.Document;
    import org.dom4j.Element;
    import org.dom4j.io.SAXReader;
    import org.junit.jupiter.api.Test;
    
    import java.io.InputStream;
    
    /**
     * 目标: 学会使用dom4j解析XML文件中的数据.
     * 1. 导入dom4j框架.
     * 2.准备一个XML文件
     */
    public class Dom4jDemo {
        @Test
        public void parseXMLData() throws Exception {
    
            // 1.创建一个dom4j的解析器对象 代表了整个dom4j框架
            SAXReader saxReader = new SAXReader();
    
            // 2.把XML文件加载到内存中成为一个Document文档对象
            // getResourceAsStream中 / 是直接去src下寻找文件
            InputStream inputStream = Dom4jDemo.class.getResourceAsStream("/students.xml");
            Document document = saxReader.read(inputStream);
    
            // 3.获取根元素
            Element root = document.getRootElement();
            // students
            System.out.println(root.getName());
            
        }
        
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    Dom4j解析XML的元素、属性、文本:

    方法名说明
    List elements()得到当前元素下所有子元素。
    List elements(String name)得到当前元素下制定名字的子元素返回集合。
    Element element(String name)得到当前元素下指定名字的子元素,如果有很多名字相同的返回第一个。
    String getName()得到元素名字。
    String attributeValue(String name)通过属性名直接得到属性值。
    String elementText(子元素名)得到指定名称的子元素的文本。
    String getText()得到文本。

    案例:XML解析案例。

    需求:

    • 利用dom4j的知识,将students.xml文件中的联系人数据封装成List集合,其中每个元素都是实体类Student,打印输出List中每个元素。

    students.xml

    
    <students>
        
        <student id="1">
            <name>花千骨name>
            <age>16age>
            <sex>sex>
            <email>hqg@changliu.comemail>
        student>
    
        
        <student id="2">
            <name>轻水name>
            <age>17age>
            <sex>sex>
            <email>qs@changliu.comemail>
        student>
    
        
        <student id="3">
            <name>孟玄朗name>
            <age>20age>
            <sex>sex>
            <email>mxl@changliu.comemail>
        student>
    
    students>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    Student.java

    public class Student {
        private int id;
        private String name;
        private int age;
        private char sex;
        private String email;
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public char getSex() {
            return sex;
        }
    
        public void setSex(char sex) {
            this.sex = sex;
        }
    
        public String getEmail() {
            return email;
        }
    
        public void setEmail(String email) {
            this.email = email;
        }
    
        public Student() {
        }
    
        public Student(int id, String name, int age, char sex, String email) {
            this.id = id;
            this.name = name;
            this.age = age;
            this.sex = sex;
            this.email = email;
        }
    
        @Override
        public String toString() {
            return "Student{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", age=" + age +
                    ", sex=" + sex +
                    ", email='" + email + '\'' +
                    '}';
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70

    Dom4jDemo.java

    import org.dom4j.Document;
    import org.dom4j.Element;
    import org.dom4j.io.SAXReader;
    import org.junit.jupiter.api.Test;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * 需求: 解析XML中的数据成为一个List集合对象
     */
    public class Dom4jDemo {
        @Test
        public void parseToList() throws Exception {
    
            // 1.创建一个dom4j的解析器对象 代表了整个dom4j框架
            SAXReader saxReader = new SAXReader();
    
            // 2.把XML文件加载到内存中成为一个Document文档对象
            Document document = saxReader.read(Dom4jDemo.class.getResourceAsStream("/students.xml"));
    
            // 3.获取根元素
            Element root = document.getRootElement();
    
            // 4.获取students子元素
            List<Element> elements = root.elements("student");
    
            // 5.准备一个ArrayList集合封装联系人信息
            List<Student> studentArrayList = new ArrayList<>();
    
            // 6.遍历students子元素
            for (Element element : elements) {
    
                // 创建Student对象
                Student student = new Student();
                student.setId(Integer.parseInt(element.attributeValue("id")));
                student.setName(element.elementTextTrim("name"));
                student.setSex(element.elementTextTrim("sex").charAt(0));
                student.setEmail(element.elementText("email"));
    
                // Student对象加入到List集合中
                studentArrayList.add(student);
            }
    
            // 7.遍历List集合
            for (Student student : studentArrayList) {
                System.out.println(student);
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    执行结果:

    Student{id=1, name='花千骨', age=0, sex=女, email='hqg@changliu.com'}
    Student{id=2, name='轻水', age=0, sex=女, email='qs@changliu.com'}
    Student{id=3, name='孟玄朗', age=0, sex=男, email='mxl@changliu.com'}
    
    • 1
    • 2
    • 3

    3.XML检索技术:XPath

    如果需要从XML中检索需要的某个信息怎么解决?

    • dom4j需要进行文件的全部解析,然后再寻找数据。
    • XPath技术更加适合做信息检索。

    XPath介绍:

    • XPath在解析XML文档方面提供了独树一帜的路径思想,更加优雅、高效。
    • XPath使用路径表达式来定位XML文档中的元素节点或属性节点。

    XPath的四大检索方案:

    • 绝对路径:采用绝对路径获取从根节点开始逐层的查找节点列表并打印信息。

      方法名说明
      /根元素/子元素/孙元素从根元素开始,一级一级向下查找,不能跨级。
    • 相对路径:先得到students根节点,然后向下一级student节点的name子节点并打印信息。

      方法名说明
      ./子元素/孙元素从当前元素开始,一级一级向下查找,不能跨级。
    • 全文检索:直接全文搜索所有的name元素并打印。

      方法名说明
      //元素在全文找这个元素。
      //元素1/元素2在全文找元素1下面的一级元素2
      //元素1//元素2在全文找元素1下面的全部元素2
    • 属性查找:在全文中搜索属性,或者带属性的元素。

      方法名说明
      //@属性名查找属性对象,无论是哪个元素,只要有这个属性即可。
      //元素[@属性名]查找元素对象,全文搜索指定元素名和属性名。
      //元素[@属性名=值]查找元素对象,全文搜索指定元素名和属性名,并且属性值相等。

    案例:使用XPath检索出XML文件。

    需求:

    • 使用dom4j把一个XML文件的数据进行解析。

    分析:

    1. 下载jaxen-x.x.x.jar https://search.maven.org/artifact/jaxen/jaxen/1.2.0/bundle

    2. 导入jar包(dom4j和jaxen),XPath技术依赖dom4j技术。

    3. 通过dom4j的SAXReader获取Document对象。

    4. 利用XPath提供的API,结合XPath的语法完成选取XML文档元素节点进行解析操作。

    5. Document中与XPath相关的API如下:

      方法名说明
      Node selectSingleNode(“表达式”)获取符合表达式的唯一元素。
      List selectNodes(“表达式”)获取符合表达式的元素集合。

    students.xml

    
    <students>
        
        <student id="1">
            <name id="111">花千骨name>
            <age>16age>
            <sex>sex>
            <email>hqg@changliu.comemail>
        student>
    
        
        <student id="2">
            <name>轻水name>
            <age>17age>
            <sex>sex>
            <email>qs@changliu.comemail>
        student>
    
        
        <student id="3">
            <name>孟玄朗name>
            <age>20age>
            <sex>sex>
            <email>mxl@changliu.comemail>
        student>
    
    students>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    XPathDemoTest.java

    import org.dom4j.Attribute;
    import org.dom4j.Document;
    import org.dom4j.Element;
    import org.dom4j.Node;
    import org.dom4j.io.SAXReader;
    import org.junit.jupiter.api.Test;
    
    import java.util.List;
    
    
    public class XPathDemoTest {
        /**
         * 1.绝对路径: /根元素/子元素/子元素.
         */
        @Test
        public void parse1() throws Exception {
            // a.创建解析器对象
            SAXReader saxReader = new SAXReader();
    
            // b.把XML加载成Document文档对象
            Document document = saxReader.read(XPathDemoTest.class.getResourceAsStream("/students.xml"));
    
            // c.检索全部姓名
            List<Node> nameNodes = document.selectNodes("/students/student/name");
    
            for (Node nameNode : nameNodes) {
                Element element = (Element) nameNode;
                // 花千骨
                // 轻水
                // 孟玄朗
                System.out.println(element.getTextTrim());
            }
        }
    
        /**
         * 2.相对路径: ./子元素/子元素
         * '.' 代表当前元素
         */
        @Test
        public void parse2() throws Exception {
            // a.创建解析器对象
            SAXReader saxReader = new SAXReader();
    
            // b.把XML加载成Document文档对象
            Document document = saxReader.read(XPathDemoTest.class.getResourceAsStream("/students.xml"));
    
            // c.获取根元素 students
            Element root = document.getRootElement();
    
            // d.检索全部姓名
            List<Node> nameNodes = root.selectNodes("./student/name");
    
            for (Node nameNode : nameNodes) {
                Element element = (Element) nameNode;
                // 花千骨
                // 轻水
                // 孟玄朗
                System.out.println(element.getTextTrim());
            }
        }
    
        /**
         * 3.全文检索:
         * //元素 在全文找这个元素
         * //元素1/元素2 在全文找元素1下面的一级元素2
         * //元素1//元素2 在全文找元素1下面的全部元素2
         */
        @Test
        public void parse3() throws Exception {
            // a.创建解析器对象
            SAXReader saxReader = new SAXReader();
    
            // b.把XML加载成Document文档对象
            Document document = saxReader.read(XPathDemoTest.class.getResourceAsStream("/students.xml"));
    
            // c.检索全部姓名
            // List nameNodes = document.selectNodes("//name");
            // List nameNodes = document.selectNodes("//students/name");
            List<Node> nameNodes = document.selectNodes("//students//name");
    
            for (Node nameNode : nameNodes) {
                Element element = (Element) nameNode;
                // 花千骨
                // 轻水
                // 孟玄朗
                System.out.println(element.getTextTrim());
            }
        }
    
        /**
         * 4.属性查找:
         * //@属性名称 在全文检索属性对象
         * //元素[@属性名称] 在全文检索包含该属性的元素对象
         * //元素[@属性名称=值] 在全文检索包含该属性的元素且属性值为该值的元素对象
         */
        @Test
        public void parse4() throws Exception {
            // a.创建解析器对象
            SAXReader saxReader = new SAXReader();
    
            // b.把XML加载成Document文档对象
            Document document = saxReader.read(XPathDemoTest.class.getResourceAsStream("/students.xml"));
    
            // c.检索包含id属性
            List<Node> nameNodes = document.selectNodes("//@id");
    
            for (Node nameNode : nameNodes) {
                Attribute attribute = (Attribute) nameNode;
                // id==>1
                // id==>111
                // id==>2
                // id==>3
                System.out.println(attribute.getName() + "==>" + attribute.getValue());
            }
    
            // 查找包含id属性的name元素
            // Node nameNode = document.selectSingleNode("//name[@id]");
            Node nameNode = document.selectSingleNode("//name[@id=111]");
            Element nameElement = (Element) nameNode;
            // 花千骨
            System.out.println(nameElement.getTextTrim());
    
    
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127

    4.设计模式:工厂模式

    什么是工厂设计模式?

    • 之前我们创建类对象时,都是使用new对象的形式创建,在很多业务场景下也提供了不直接new的方式。
    • 工厂模式(Factory Pattern)是Java中最常用的设计模式之一,这种类型的设计模式属于创建型模式,它提供了一种获取对象的方式。

    工厂设计模式的作用:

    • 工厂的方法可以封装对象的创建细节,比如:为该对象进行加工和数据注入。
    • 可以实现类与类之间的解耦操作(核心思想)。

    Computer.java

    /**
     * 电脑类
     */
    public abstract class Computer {
        private String name;
        private double price;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public double getPrice() {
            return price;
        }
    
        public void setPrice(double price) {
            this.price = price;
        }
    
        public Computer() {
        }
    
        public Computer(String name, double price) {
            this.name = name;
            this.price = price;
        }
    
        public abstract void start();
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    Mac.java

    /**
     * Mac电脑类
     */
    public class Mac extends Computer{
    
        /**
         * 开机
         */
        @Override
        public void start() {
            System.out.println(getName() + "开机,展示苹果Logo!");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    Dell.java

    /**
     * Dell电脑
     */
    public class Dell extends Computer{
        /**
         * 开机
         */
        @Override
        public void start() {
            System.out.println(getName() + "开机,并展示戴尔Logo!");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    FactoryPattern.java

    package com.javase.factorydemo;
    
    /**
     * 工厂模式
     */
    public class FactoryPattern {
        /**
         * 创建对象返回
         */
        public static Computer createComputer(String info) {
            switch (info) {
                case "Mac":
                    Computer mac = new Mac();
                    mac.setName("Macbook Pro M1 Pro");
                    mac.setPrice(14899);
                    return mac;
                case "Dell":
                    Computer dell = new Dell();
                    dell.setName("Dell 灵越 16 Plus");
                    dell.setPrice(16298.98);
                    return dell;
                default:
                    return null;
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    总结:

    1. 工厂设计模式的作用:

      • 对象通过工厂的方法创建返回,工厂的方法可以为该对象进行加工和数据注入。
      • 可以实现类与类的解耦操作(核心思想)。

    5.设计模式:装饰模式

    什么是装饰设计模式?

    • 创建一个新类,包装原始类,从而在新类中提升原来类的功能。

    装饰设计模式的作用:

    • 作用:装饰模式指的是在不改变原类的基础上,动态地扩展一个类的功能。

      InputStream(抽象父类)
      
      FileInputStream(实现子类,读写性能较差)
      
      BufferedInputStream(实现子类,装饰类,读写性能高)
      
      • 1
      • 2
      • 3
      • 4
      • 5
    • 步骤:

      1. 定义父类。
      2. 定义原始类,继承父类,定义功能。
      3. 定义装饰类,继承父类,包装原始类,增强功能。

    InputStream.java

    /**
     * 共同父类
     */
    public abstract class InputStream {
        public abstract int read();
        public abstract int read(byte[] bytes);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    FileInputStream.java

    import java.util.Arrays;
    
    /**
     * 原始类
     */
    public class FileInputStream extends InputStream {
    
        @Override
        public int read() {
    
            System.out.println("低性能的方式读取了一个字节a");
    
            return 97;
        }
    
        @Override
        public int read(byte[] bytes) {
            bytes[0] = 97;
            bytes[1] = 98;
            bytes[2] = 99;
    
            System.out.println("低性能的方式读取了一个字节数组" + Arrays.toString(bytes));
            return 3;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    BufferedInputStream.java

    /**
     * 装饰类
     */
    public class BufferedInputStream extends InputStream{
    
        private InputStream inputStream;
    
        public BufferedInputStream(InputStream inputStream) {
            this.inputStream = inputStream;
        }
    
        @Override
        public int read() {
            System.out.println("提供8KB的缓冲区,提高读数据性能!");
            return inputStream.read();
        }
    
        @Override
        public int read(byte[] bytes) {
            System.out.println("提供8KB的缓冲区,提高读数据性能!");
    
            return inputStream.read(bytes);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    DecoratorPattern.java

    public class DecoratorPattern {
        public static void main(String[] args) {
            InputStream inputStream = new BufferedInputStream(new FileInputStream());
    
            System.out.println(inputStream.read());
            System.out.println(inputStream.read(new byte[3]));
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    执行结果:

    提供8KB的缓冲区,提高读数据性能!
    低性能的方式读取了一个字节a
    97
    提供8KB的缓冲区,提高读数据性能!
    低性能的方式读取了一个字节数组[97, 98, 99]
    3
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    总结:

    1. 装饰设计模式的作用?
      • 装饰模式指的是在不改变原类的基础上,动态地扩展一个类的功能。
  • 相关阅读:
    2.19 emoji符号大全【玩赚小红书】
    学习笔记——动态路由——RIP(RIP工作原理/防环机制)
    java计算机毕业设计网上教学管理系统源代码+数据库+系统+lw文档
    【Android】系统启动流程(zygote 进程启动流程)
    Jmeter系列(4) 线程属性详解
    初探词法分析实验
    原始套接字
    如何把一个接口设计好?
    Go 语言为什么不支持并发读写 map?
    Kubernetes(31):kubeasz安装三主两从高可用集群
  • 原文地址:https://blog.csdn.net/weixin_42856871/article/details/127706488