Java设计之道——通过UML理解23种设计模式_下面的javaiouml类图体现了哪种设计模式思想-CSDN博客(有图最好的)

13.工厂方法设计模式 - 掘金

基于Java的XML操作(XML使用、解析、生成)_javaxml islabel-CSDN博客

XML操作:

基于Java的XML操作(XML使用、解析、生成)_javaxml islabel-CSDN博客

DOM4j解析XML:

【精选】Dom4j解析XML(详解)_dom4j解析xml文件_散一世繁华,颠半世琉璃的博客-CSDN博客
1.导入依赖

1
2
3
4
5
6
7
8
<dependencies>
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.1.1</version>
</dependency>
</dependencies>

2.准备的XML:

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="UTF-8"?>
<books>
<book id="1">
<name>鬼谷子</name>
<info>教你如何识人,谋略,管理。。。</info>
</book>
<book id="2">
<name>白雪公主</name>
<info>白雪公主与七个小矮人的故事</info>
</book>
</books>

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package XML;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;
/**
* @author redA
* @时间: 2023年10月21日 12:46
* DOM4J解析XML
*/
public class Demo01 {
public static void main(String[] args) throws IOException, DocumentException {
//1、获取输入流
FileInputStream fis = new FileInputStream("test/src/test/java/XML/demo.xml");
//2、创建xml读取对象
SAXReader sr = new SAXReader();
//3、读取并获得文档
Document doc = sr.read(fis);
//4、通过文档获取根元素
Element root = ((org.dom4j.Document) doc).getRootElement();
//5、开始解析元素
System.out.println(root.getName());
//常见操作
/*Element book = root.element("book");
Element name = book.element("name");
System.out.println(name.getText());*/
List<Element> list = root.elements();
for (int i = 0; i < list.size(); i++) {
Element element = list.get(i);
System.out.println(element.attributeValue("id"));
System.out.println(element.elementText("name"));
System.out.println(element.elementText("info"));
System.out.println("-------------------");
}
fis.close();
}
}

dom4j结合XPath解析XML

1.导入依赖:
上面的dom4j依赖还需要额外的依赖:在pom.xml导入Xpath对应的依赖即可,具体如下所示:

1
2
3
4
5
6
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.2.0</version>
</dependency>

测试:

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
package XML;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

import java.io.FileInputStream;
import java.io.IOException;

/**
* @author redA
* @时间: 2023年10月21日 13:09
*/
public class Demo03 {
public static void main(String[] args) throws DocumentException, IOException {
//1、获取输入流
FileInputStream fis = new FileInputStream("test/src/test/java/XML/demo.xml");
//2、创建xml读取对象
SAXReader sr = new SAXReader();
//3、读取并获得文档
Document doc = sr.read(fis);
Node node = doc.selectSingleNode("//book[@id='1']//name");
System.out.println(node.getName()+":"+node.getText());
fis.close();
}
}

DEMO4J生成XML文件:

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
public class SaveGrandpa {
public static void main(String[] args) throws IOException {
//1、通过文档助手,创建一个文档对象
Document document = DocumentHelper.createDocument();
//2、给文档添加第一个节点(根节点)
Element books = document.addElement("books");
for (int i = 0; i < 100; i++) {
Element book = books.addElement("book");//添加books节点下的节点book
Element name = book.addElement("name");//添加book节点下的节点name
name.setText("葫芦娃救爷爷第("+i+")集");
Element info = book.addElement("info");//添加book节点下的节点info
info.setText("爷爷第"+i+"次被抓走后,葫芦兄弟们,开始了他们第"+i+"次的行动计划");
book.addAttribute("id",100+i+"");//给定book一个id属性,还有其对应的值
}
//4、创建一个文件输出流
FileOutputStream fos = new FileOutputStream("test/src/test/java/XML/book.xml");
//5、将输出流转换为XML输出流
XMLWriter xw = new XMLWriter(fos);
//6、写出文档
xw.write(document);
//释放资源
xw.close();
System.out.println("执行完毕");
}
}

XML解析之DOM解析

XML解析之DOM解析详解_dom xml-CSDN博客

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class DOMDemo01 {

public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException, IOException, SAXException {
//建立DocumentBuilderFactor,用于获得DocumentBuilder对象:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
//2.建立DocumentBuidler:
DocumentBuilder builder = factory.newDocumentBuilder();
//3.建立Document对象,获取树的入口:
Document doc = builder.parse("test/src/test/java/XML/demo.xml");
//4.建立NodeList:
NodeList node = doc.getElementsByTagName("book");
//5.进行xml信息获取
for(int i=0;i<node.getLength();i++){
Element e = (Element)node.item(i);
// e.getElementsByTagName("name")返回name标签下所有名为name的标签集合;.item(0)获取
// 索引为0的标签集合;.getFirstChild()获取该标签下的第一个子节点(和前端的DOM树一个概念,文本信息也是节点)
System.out.println("书名:"+
e.getElementsByTagName("name").item(0).getFirstChild().getNodeValue());
System.out.println("信息:"+
e.getElementsByTagName("info").item(0).getFirstChild().getNodeValue());
}

}
}

运行结果:
image.png

反射:

Java反射(超详细!)_一个快乐的野指针~的博客-CSDN博客(最好)
深入理解Java反射机制原理、使用方法_反射获取 hashmap 成员_涝山道士的博客-CSDN博客
Java反射详解:入门+使用+原理+应用场景 - mikechen的互联网架构 - 博客园(原理)
一篇图文彻底弄懂Class文件是如何被加载进JVM的_classloader加载class之后,class内容放在那里-CSDN博客(类加载原理)
一看你就懂,超详细java中的ClassLoader详解-CSDN博客(详细较难)

1
JVM加载class要经历加载连接和初始化阶段。

设计模式七大准则:

万字总结之设计模式七大原则 - 掘金

工厂设计模式:

简单工厂模式:

工厂方法模式:

抽象工厂:

设计模式学习笔记(三)简单工厂、工厂方法和抽象工厂之间的区别 - 掘金(较难)
1.简单工厂设计模式 - 掘金
13.工厂方法设计模式 - 掘金
java工厂模式:简单工厂、工厂方法、抽象工厂(通俗易懂)_Mitsuha三葉的博客-CSDN博客
简单工厂是一个工厂方法承担多个产品制造方法。工厂方法是每个产品有一个公共的工厂类,各个工厂类抽象了一个接口,供上层模块使用。抽象工厂有多个工厂(抽象工厂+多个具体工厂),多个产品接口/抽象类,对产品子类进行分组,根据继承抽象工厂中的方法多态创建同组的不同具体产品对象。适用于多个类型的多个产品。抽象工厂:比如有多个产品,这多个产品中每种产品有多种特性,我们把其中的一些特性抽取出来为多个接口,让这些产品实现这些接口;然后把部分特性放在工厂类中,工厂类在制造这些产品的时候给这些产品附加一些特性,然后把各个工厂类抽象为一个抽象工厂类供上层模块使用。

适配器模式:

秒懂设计模式之适配器模式(Adapter Pattern)
设计模式之结构型模式的设计与实现(一)
分为对象适配器模式和类适配器模式。
image.png

桥接模式:

桥接模式实例与解析 实例一:模拟毛笔_桥接模式 毛笔-CSDN博客
详解设计模式:桥接模式-腾讯云开发者社区-腾讯云

外观模式:


(简单来说就是将多个类的功能集中到一个外观类中,让这个外观类去调用各个类的方法)
【设计模式】外观模式 ( 概念 | 适用场景 | 优缺点 | 代码示例 )_外观模式的优缺点-CSDN博客
外观模式 ------模拟电脑主机调用其他硬件和软件_模拟连接计算机硬件_寻常w的博客-CSDN博客
外观模式_使用外观模式,描述cpu、memory、disk、电脑几个对象-CSDN博客

代理模式:

静态代理:需要实现接口的原因是为了可以用接口来代替代理类。

动态代理:不需要实现接口但是因为利用了反射机制;AOP编程使用的就是动态代理

设计模式——代理模式 | 程序员进阶
代理模式(二):代理模式应用实例(收费商务信息查询系统)-CSDN博客
Java代理模式:如何优雅地控制对象访问? - 掘金

命令模式:

image.png
深入理解设计模式(十):命令模式 - 一指流砂~ - 博客园
【精选】命令模式模拟房间开关_房间中的开关就是命令模式的一个实现_水木 清华的博客-CSDN博客

迭代器模式:


【精选】Java迭代器详解,看这一篇就够了-CSDN博客
【设计模式】迭代器模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )_迭代器模式优缺点-CSDN博客
设计模式学习笔记(十六)迭代器模式及其在Java 容器中的应用-腾讯云开发者社区-腾讯云

观察者模式:


深入理解设计模式(八):观察者模式 - 一指流砂~ - 博客园
设计模式之《观察者模式》 - 掘金
观察者模式-猫叫了,老鼠跑了,主人醒了… - Binyao - 博客园

策略模式:

Java设计模式之(十四)——策略模式 - YSOcean - 博客园
【设计模式】用Java实现策略模式_java策略模式实现_卷帘的博客-CSDN博客
Java的设计模式(5)-- 策略模式 - 扁豆一号 - 博客园

访问者模式:

访问者模式一篇就够了
访问者模式是一种将数据操作和数据结构分离的设计模式。
image.png

复习:

建造者模式:

image.png
建造者模式在创建产品的时候使用的是Director中的创造产品方法,而该方法的参数是Builder接口的具体实现类,而这个具体实现类的作用是产生一个具体的产品(该产品的属性赋值了的);这样做就可以把产品的生成和赋值分离开来。比如当一个产品融合到一个模块中了,如果该产品是用new生成在赋值的,那么我们想修改该产品的属性就需要修改这个模块;如果我们使用了构造者模式,我们就把该产品赋值分离了该模块也就是是把赋值的功能交给了Builder具体实现类,我们只需要修改这个具体实现类而不用修改原模块了。
23种设计模式全解析(JAVA实现)_23种设计模式 java实现、-CSDN博客

原型模式:

设计模式——原型模式 | 程序员进阶
image.png

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
package com.yintong.principle.singleresponsibility;
//写一个手机的克隆类
public class ConcretePrototype implements Cloneable{
// 这里的Cloneable是一个空接口,起着标记的作用
//名称
private String name;
//号码
private Long number;
//构造器
public ConcretePrototype(String name, Long number) {
super();
this.name = name;
this.number = number;
}

@Override
public String toString() {
return "ConcretePrototype [name=" + name + ", number=" + number + "]";
}
// 克隆用到的主要部分,重写的clone方法是object中的方法,Object
// 中的clone方法用于创建并返回当前对象的副本。如果当前对象的类实现了Cloneable接口,
// 则返回新的对象,否则抛出CloneNotSupportedException异常。
//
@Override
protected Object clone() throws CloneNotSupportedException {
ConcretePrototype ConcretePrototype = null;
try {
ConcretePrototype = (ConcretePrototype) super.clone();
}catch (Exception e) {
System.out.println(e.getMessage());
}
return ConcretePrototype;
}
}

1
2
3
4
5
6
7
8
9
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
//创建一个对象
ConcretePrototype prototype = new ConcretePrototype("华为", new Long(1568889932));
//通过原型模式完成对象的创建 克隆
ConcretePrototype p2 = (ConcretePrototype)prototype.clone();
}
}
// 这里的p2和 prototype创建对象的地址不一样

单例模式:

通过构造方法私有化,在类中实例该对象,从而达到单例的效果。

组合模式:

主要表现的是类的层次结构
image.png

装饰者模式:

Java设计模式——装饰模式_装饰模式代码-CSDN博客
动态地给一个对象添加一些额外的职责的同时不修改原对象;这里的原对象是ConcreteComponent的实例,在不修改原对象添加额外的操作说白了就是新创建一个类,这个类属性为原对象,把这个类的实例当作原对象的实例,通过往该类中添加额外的操作来实现。这里之所以抽出一个接口是为了让类依赖于接口而不是具体的类。

Component:对象的接口类,定义装饰对象和被装饰对象的共同接口;
ConcreteComponent:被装饰对象的类定义;
Decorator:装饰对象的抽象类,持有一个具体的被修饰对象,并实现接口类继承的公共接口;
ConcreteDecorator:具体的装饰器,负责往被装饰对象添加额外的功能;

享元模式:

设计模式——享元模式 | 程序员进阶

职责链模式:

就是客户端将请求request包装为一个request该request发给一个抽象的handler类,该handler有多个实现类;
这种模式深刻体现了依赖倒置原则。

访问者模式:

将数据结构的操作和数据结构分离开来。

中介模式:

当一个类依赖一个类是,不直接使用依赖而是通过中介来实现这种依赖关系。迪米特法则当传递过来的参数是数组的时候,该类中对该数组参数的处理可能会new一个该参数的类,这个时候就破坏了迪米特法则;利用中介模式可以很好的维护迪米特法则。

备忘录模式:

在不破坏一个对象封装性的前提下,获取该对象内部状态。

状态模式:

当对象的状态改变时,同时改变其行为。也就是行为由其状态决定。

策略模式:

定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。

模板模型:

习题:

image.png
image.png

1
2
3
4
5
6
合成复用实际上更倾向于"黑箱"复用,而不是"白箱"复用。在合成复用中,包含对象的容器对象并不需要了
解或暴露被包含对象的实现细节,因此称为"黑箱"复用。这种方式降低了对象之间的耦合度,并且使得容
器对象可以独立于被包含对象进行变化。

另外,合成复用是可以在运行时动态实现的,通过组合对象,可以在运行时灵活地改变对象之间的关系。
这使得合成复用比继承复用更加灵活和可扩展。因此,选项B的说法是错误的。

image.png
image.png
image.png

1
2
3
4
5
6
7
8
桥接模式将对象的抽象部分与它的实现部分分离,以使得它们都可以独立地变化。在桥接模式中,
一个对象被划分成两个部分,即抽象部分和实现部分,然后两者通过桥进行关联。
这样,抽象部分和实现部分可以分别独立地变化,而不会影响到它们之间的耦合关系。
状态模式则是一种行为型模式,用于模拟对象的各种状态,并且方便在不同状态之间进行转换。
状态模式包含状态接口、具体状态以及上下文三个部分。其中,状态接口定义了各个具体状态的共同行为,
具体状态则实现了这些行为,而上下文则包含了状态接口,并且通过引用具体状态来实现状态的切换。
因此,桥接模式和状态模式的作用和实现方式是不同的。桥接模式主要用于对象的抽象和实现的分离,
而状态模式主要用于模拟对象的不同状态和状态之间的切换。

image.png
image.png

1
封装不仅仅包括数据,还包括一些方法

image.png
简单工厂模式的类图:

可以看到如果新增一个具体产品的话,就需要修改Factory中的构造方法,明显不符合开闭原则。
image.png(这个题应该有点争议)
原型模式clone的对象不一样,但是类型一样。
image.png
这个说的应该是桥接模式,抽象工厂针对的是多个产品等级结构。

image.png
饿汉式是随着类加载的时候创建实例,懒汉式是需要使用的时候加载实例,其存在线程安全问题。
单例模型的作用就是保证一个类仅有一个实例,并提供一个访问他的全局访问点。
image.png
image.png

1
正确。如果对象x的equals()方法定义恰当,那么x.clone().equals(x)应该成立。这是因为Cloneable接口的clone()方法会创建一个与原始对象相同的对象,并返回该对象。然后,通过调用equals()方法比较两个对象是否相等。在这种情况下,x.clone().equals(x)应该返回true,表示两个对象相等。

image.png
建造者模式是将对象的创建和赋值给分离开的模式,这里汽车的反向盘等是可以用其他来替换的;

1
组合模式是一种用于组合对象以形成树形结构的模式。它允许动态地添加和删除对象,同时保持了对象的层次结构。组合模式使用分层的结构来表示整体和部分的关系,部分可以是另一个整体。组合模式适用于需要对对象进行遍历和访问的情况。  建造者模式是一种用于将对象的不同部分组合成一个完整对象的模式。它将对象的构造过程分离出来,以便可以单独管理和改变这个过程。建造者模式适用于当需要创建复杂对象时,这些对象的构建过程很复杂,很难通过简单的赋值来实现。  总之,组合模式是用于组合对象以形成树形结构的模式,而建造者模式是用于将对象的不同部分组合成一个完整对象的模式


上面的题如果选中组合模式,那么发动机和方向盘都需要实现统一的接口,这在现实世界中是不现实的。image.png

1
在原型模式中,每个具体原型类都需要实现一个克隆方法(Clone Method),该方法用于创建并返回当前对象的副本。因此,对于每个类都需要配置一个克隆方法,以便实现原型对象的复制。

image.png
image.png
image.png
image.png
职责链模式是将处理请求传递给下一个处理者。如果上面使用的是职责链模式,那么系统会在判断教师是否满足科研奖后自动继续判断是否教师满足成绩优秀奖;这明显是不符合题目需求的:判断是否符合某个奖项而不是判断能拿哪些奖项。因此这里该使用访问者模式,将某种具体的奖项当成一种数据结构,而判断是否满足当成访问者(数据的操作)。

1
模板方法模式(Template Method Pattern)是一种行为型模式,它定义了一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义算法的某些特定步骤。

image.png
A

1
职责链模式是一种行为型设计模式,用于解决一组对象对同一消息做出响应的问题。职责链模式通过创建一个对象链,使得多个对象都有机会处理请求,从而避免了传统的多分支处理请求的模式。其中,每个对象都有机会处理请求,而客户端只需知道最终处理请求的对象,而不需要了解链上的其他对象。 
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
// 职责链模式示例代码

// 职责接口
interface Handler {
boolean handleRequest(int request);
}

// 具体职责类
class ConcreteHandler1 implements Handler {
private Handler nextHandler;

@Override
public boolean handleRequest(int request) {
if (request >= 10 && request <= 15) {
return true;
}
if (nextHandler != null) {
return nextHandler.handleRequest(request);
}
return false;
}

public void setNext(Handler nextHandler) {
this.nextHandler = nextHandler;
}
}

class ConcreteHandler2 implements Handler {
private Handler nextHandler;

@Override
public boolean handleRequest(int request) {
if (request >= 5 && request <= 10) {
return true;
}
if (nextHandler != null) {
return nextHandler.handleRequest(request);
}
return false;
}

public void setNext(Handler nextHandler) {
this.nextHandler = nextHandler;
}
}

// 客户端代码
public class Client {
public static void main(String[] args) {
Handler handler1 = new ConcreteHandler1();
Handler handler2 = new ConcreteHandler2();
handler1.setNext(handler2);

boolean result = handler1.handleRequest(7);
System.out.println(result); // 输出 true
}
}

image.png
A

1
产品等级是同一产品族之间的划分,主要是由产品构造类决定的