0%


应用协议都有哪些

  • 域名系统(Domain Name System,DNS):用于实现网络设备名字到IP地址映射的网络服务。
  • 文件传输协议(File Transfer Protocol,FTP):用于实现交互式文件传输功能。
  • SMTP是一种提供可靠且有效电子邮件传输的协议。SMTP 是建模在 FTP 文件传输服务上的一种邮件服务,SMTP 服务器在默认端口 25 上监听客户请求,主要用于传输系统之间的邮件信息。
  • 简单网络管理协议(simple Network Management Protocol,SNMP):用于管理与监视网络设备。
  • 远程登录协议(Telnet):用于实现远程登录功能。
  • 超文本传输协议(HyperText Transfer Protocol,HTTP):超文本传输协议,是一个基于请求与响应,无状态的,应用层的协议,常基于TCP/IP协议传输数据,互联网上应用最为广泛的一种网络协议,所有的WWW文件都必须遵守这个标准。设计HTTP的初衷是为了提供一种发布和接收HTML页面的方法。请求和响应消息的头以ASCII形式给出。

延展了解:WWW是什么
凡是上网的人,谁不知道“WWW”的重要作用?要输入网址,首先得打出这三个字母来。
万维网是无数个网络站点和网页的集合,它们在一起构成了因特网最主要的部分。

(伯纳斯·李,在世界上最大型的粒子物理学实验室-欧洲核子研究组织,发明了万维网。)

二.在我上网的过程中,都发生了什么

1.打开浏览器,输入网址URL,看看都有什么

a

2.通过访问的域名找出其IP地址(专门保存了 Web 服务器域名与 IP 的对应关系,它就是 DNS 服务器)

b

3.浏览器发出读取文件(URL 中域名后面部分对应的文件)的HTTP 请求,该请求报文作为 TCP 三次握手的第三个报文的数据发送给服务器

  • 请求长这样
    c
    • (请求方法一般有:GET、POST、PUT、DELETE等)
    • POST和GET区别(传参方式一个通过 url,一个通过正文)
  • 接下来应用程序(浏览器)通过调用 Socket 库,来委托协议栈工作。协议栈的上半部分有两块,分别是负责收发数据的 TCP 和 UDP 协议,它们两会接受应用层的委托执行收发数据的操作。
    d

  • 在 HTTP 传输数据之前,首先需要 TCP 建立连接,TCP 连接的建立,通常称为三次握手。这个所谓的「连接」,只是双方计算机里维护一个状态机,在连接建立的过程中,双方的状态变化时序图就像这样。

  • e
  • 一开始,客户端和服务端都处于 CLOSED 状态。先是服务端主动监听某个端口,处于 LISTEN 状态。
    然后客户端主动发起连接 SYN,之后处于 SYN-SENT 状态。
    服务端收到发起的连接,返回 SYN,并且 ACK 客户端的 SYN,之后处于 SYN-RCVD 状态。
    客户端收到服务端发送的 SYN 和 ACK 之后,发送 ACK 的 ACK,之后处于 ESTABLISHED 状态,因为它一发一收成功了。
    服务端收到 ACK 的 ACK 之后,处于 ESTABLISHED 状态,因为它也一发一收了。
  • (延展阅读SYN攻击属于DDoS攻击的一种,它利用TCP协议缺陷,通过发送大量的半连接请求,耗费CPU和内存资源。)
  • TCP 报文生成。在双方建立了连接后,TCP 报文中的数据部分就是存放 HTTP 头部 + 数据,组装好 TCP 报文之后,就需交给下面的网络层处理。
  • 至此,网络包的报文如下图。
  • f
  • IP 报文生成。
  • g
  • MAC 报文生成。
  • h
  • 最后网络包格式
  • i
  • 网卡驱动从 IP 模块获取到包之后,会将其复制到网卡内的缓存区中,接着会其开头加上报头和起始帧分界符,在末尾加上用于检测错误的帧校验序列。
  • j
  • 互相扒皮 —— 服务器 与 客户端
  • k

4.服务器给浏览器响应一个301永久重定向响应

5.浏览器跟踪重定向地址

6.服务器处理请求


7.服务器对浏览器请求作出响应,并把对应的 html 文本发送给浏览器

Web服务器解析请求,定位请求资源。服务器将资源复本写到TCP套接字,由客户端读取。一个响应由状态行、响应头部、空行和响应数据4部分组成。
HTTP响应与HTTP请求相似,HTTP响应也由3个部分构成,分别是:

  • 状态行:由协议版本、数字形式的状态代码<1xx,2xx,4xx,5xx>、及相应的状态描述,各元素之间以空格分隔。)示例:HTTP/1.1 200 OK \r\n
  • 响应头(Response Header):由关键字/值对组成,每行一对,关键字和值用英文冒号”:”分隔。示例:l
  • 响应正文:包含着我们需要的一些具体信息,比如cookie,html,image,后端返回的请求数据等等。这里需要注意,响应正文和响应头之间有一行空格,表示响应头的信息到空格为止

    8.浏览器显示 HTML

    9.浏览器发送请求获取嵌入在 HTML 中的资源(如图片、音频、视频、CSS、JS等等)


三.问题来了

  • 1.现代浏览器在与服务器建立了一个 TCP 连接后是否会在一个 HTTP 请求完成后断开?什么情况下会断开?
  • 2.一个 TCP 连接可以对应几个 HTTP 请求?
  • 3.一个 TCP 连接中 HTTP 请求发送可以一起发送么(比如一起发三个请求,再三个响应一起接收)?
  • 4.浏览器对同一 Host 建立 TCP 连接到数量有没有限制?




















四.原来如此

  • 1.现代浏览器在与服务器建立了一个 TCP 连接后是否会在一个 HTTP 请求完成后断开?什么情况下会断开?
    答:在 HTTP/1.0 中,一个服务器在发送完一个HTTP 响应后,会断开 TCP 链接。但是这样每次请求都会重新建立和断开 TCP 连接,代价过大。既然维持TCP 连接好处这么多,HTTP/1.1 就把 Connection 头写进标准,并且默认开启持久连接,除非请求中写明 Connection: close,那么浏览器和服务器之间是会维持一段时间的 TCP 连接,不会一个请求结束就断掉。
  • 2.一个 TCP 连接可以对应几个 HTTP 请求?
    答:如果维持连接,一个 TCP 连接是可以发送多个 HTTP 请求的。
  • 3.一个 TCP 连接中 HTTP 请求发送可以一起发送么(比如一起发三个请求,再三个响应一起接收)?
    答:在 HTTP/1.1 存在 Pipelining 技术可以完成这个多个请求同时发送,但是由于浏览器默认关闭,所以可以认为这是不可行的。在 HTTP2 中由于 Multiplexing 特点的存在,多个 HTTP 请求可以在同一个 TCP 连接中并行进行。

  • 4.浏览器对同一 Host 建立 TCP 连接到数量有没有限制?
    答:有。Chrome 最多允许对同一个 Host 建立六个 TCP 连接。不同的浏览器有一些区别。


五.HTTP1.0 & HTTP1.1 & HTTP2.0

3.png

1.HTTP1.0和HTTP1.1的区别

  • 长连接(Persistent Connection)
    HTTP1.1支持长连接和请求的流水线处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启长连接keep-alive,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。HTTP1.0需要使用keep-alive参数来告知服务器端要建立一个长连接。
  • 节约带宽
    HTTP1.0中存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能。HTTP1.1支持只发送header信息(不带任何body信息),如果服务器认为客户端有权限请求服务器,则返回100,客户端接收到100才开始把请求body发送到服务器;如果返回401,客户端就可以不用发送请求body了节约了带宽。
  • HOST域
    在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname),HTTP1.0没有host域。随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都支持host域,且请求消息中如果没有host域会报告一个错误(400 Bad Request)。
  • 缓存处理
    在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准,HTTP1.1则引入了更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略。
  • 错误通知的管理
    在HTTP1.1中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。

2.HTTP1.1和HTTP2.0的区别

  • HTTP/2 采用二进制格式传输数据
  • 多路复用
    HTTP2.0使用了多路复用的技术,做到同一个连接并发处理多个请求,而且并发请求的数量比HTTP1.1大了好几个数量级。HTTP1.1也可以多建立几个TCP连接,来支持处理更多并发的请求,但是创建TCP连接本身也是有开销的。
  • 头部数据压缩
    在HTTP1.1中,HTTP请求和响应都是由状态行、请求/响应头部、消息主体三部分组成。一般而言,消息主体都会经过gzip压缩,或者本身传输的就是压缩过后的二进制文件,但状态行和头部却没有经过任何压缩,直接以纯文本传输。随着Web功能越来越复杂,每个页面产生的请求数也越来越多,导致消耗在头部的流量越来越多,尤其是每次都要传输UserAgent、Cookie这类不会频繁变动的内容,完全是一种浪费。
  • HTTP1.1不支持header数据的压缩,HTTP2.0使用HPACK算法对header的数据进行压缩,这样数据体积小了,在网络上传输就会更快。
  • 服务器推送
    服务端推送是一种在客户端请求之前发送数据的机制。网页使用了许多资源:HTML、样式表、脚本、图片等等。在HTTP1.1中这些资源每一个都必须明确地请求。这是一个很慢的过程。浏览器从获取HTML开始,然后在它解析和评估页面的时候,增量地获取更多的资源。因为服务器必须等待浏览器做每一个请求,网络经常是空闲的和未充分使用的。 为了改善延迟,HTTP2.0引入了server push,它允许服务端推送资源给浏览器,在浏览器明确地请求之前,免得客户端再次创建连接发送请求到服务器端获取。这样客户端可以直接从本地加载这些资源,不用再通过网络。

六.HTTPS

HTTP请求过程中,客户端与服务器之间没有任何身份确认的过程,数据全部明文传输,“裸奔”在互联网上,所以很容易遭到黑客的攻击。

下面两图中,浏览器中填入的是相同的URL,左边是正确响应,而右边则是被劫持后的响应
s
所以 HTTP 传输面临的风险有:

(1) 窃听风险:黑客可以获知通信内容。

(2) 篡改风险:黑客可以修改通信内容。

(3) 冒充风险:黑客可以冒充他人身份参与通信。


为了防止上述现象的发生,人们想到一个办法:对传输的信息加密(即使黑客截获,也无法破解)

(关于加密方式)

  • 对称加密
    • 这种方式加密和解密同用一个密钥。加密和解密都会用到密钥。没有密钥就无法对密码解密,反过来说,任何人只要持有密钥就能解密了。
  • 非对称加密

    • 使用公开密钥加密方式,发送密文的一方使用对方的公开密钥进行加密处理,对方收到被加密的信息后,再使用自己的私有密钥进行解密。利用这种方式,不需要发送用来解密的私有密钥,也不必担心密钥被攻击者窃听而盗走。
    • 缺点:公钥是公开的,所以针对私钥加密的信息,黑客截获后可以使用公钥进行解密,获取其中的内容;

      • 公钥并不包含服务器的信息,使用非对称加密算法无法确保服务器身份的合法性,存在中间人攻击的风险,服务器发送给客户端的公钥可能在传送过程中被中间人截获并篡改;

      • 使用非对称加密在数据加密解密过程需要消耗一定时间,降低了数据传输效率;

  • 结合两者

    • 对称加密+非对称加密(HTTPS采用这种方式)
    • 发送密文的一方使用对方的公钥进行加密处理“对称的密钥”,然后对方用自己的私钥解密拿到“对称的密钥”,这样可以确保交换的密钥是安全的前提下,使用对称加密方式进行通信
  • 假如 Alice 向 Bob 传送数字信息,为了保证信息传送的保密性、真实性、完整性和不可否认性,需要对传送的信息进行数字加密和签名,其传送过程为

    • Alice 准备好要传送的数字信息(明文); [3]
      • Alice 对数字信息进行哈希运算,得到一个信息摘要; [3]
      • Alice 用自己的私钥对信息摘要进行加密得到 Alice 的数字签名,并将其附在数字信息上; [3]
      • Alice 随机产生一个加密密钥,并用此密码对要发送的信息进行加密,形成密文; [3]
      • Alice 用 Bob 的公钥对刚才随机产生的加密密钥进行加密,将加密后的 DES密钥连同密文一起传送给Bob; [3]
      • Bob 收到 Alice 传送来的密文和加密过的 DES 密钥,先用自己的私钥对加密的 DES 密钥进行解密,得到 Alice随机产生的加密密钥; [3]
      • Bob 然后用随机密钥对收到的密文进行解密,得到明文的数字信息,然后将随机密钥抛弃; [3]
      • Bob 用 Alice 的公钥对 Alice 的数字签名进行解密,得到信息摘要; [3]
      • Bob 用相同的哈希算法对收到的明文再进行一次哈希运算,得到一个新的信息摘要; [3]
      • Bob 将收到的信息摘要和新产生的信息摘要进行比较,如果一致,说明收到的信息没有被修改过。 [3]
  • 如何证明公钥的真实性
    • CA证书颁发机构
    • 证书包含以下信息:申请者公钥、申请者的组织信息和个人信息、签发机构 CA的信息、有效时间、证书序列号等信息的明文,同时包含一个签名。

思考题:HTTPS能被劫持吗

创建型模式

  • 对类的实例化过程进行了抽象,能够将软件模块中对象的创建和对象的使用分离。为了使软件的结构更加清晰,外界对于这些对象只需要知道它们共同的接口,而不清楚其具体的实现细节,使整个系统的设计更加符合单一职责原则。

建造者模式(Builder pattern)

  • 在用户不知道对象的建造过程和细节的情况下就可以直接创建复杂的对象。

在这里插入图片描述

  • Product: 最终要生成的对象,例如 Computer实例。
  • Builder: 构建者的抽象基类(有时会使用接口代替)。其定义了构建Product的抽象步骤,其实体类需要实现这些步骤。其会包含一个用来返回最终产品的方法Product getProduct()。
  • ConcreteBuilder: Builder的实现类。
  • Director: 指挥者,决定如何构建最终产品的算法. 其会包含一个负责组装的方法void Construct(Builder builder), 在这个方法中通过调用builder的方法,就可以设置builder,等设置完成后,就可以通过builder的 getProduct() 方法获得最终的产品。

示例代码

1
2
3
4
ComputerDirector director=new ComputerDirector();//1
ComputerBuilder builder=new MacComputerBuilder("I5处理器","三星125");//2
director.makeComputer(builder);//3
Computer macComputer=builder.getComputer();//4
  • 首先生成一个director ,
  • 然后生成一个目标builder ,
  • 接着使用director组装builder,
  • 组装完毕后使用builder创建产品实例

实例讲解

背景:小成希望去电脑城买一台组装的台式主机
过程:

  1. 电脑城老板(Diretor)和小成(Client)进行需求沟通(买来打游戏?学习?)
  2. 了解需求后,电脑城老板将小成需要的主机划分为各个部件(Builder)的建造请求(CPU、主板blabla)
  3. 指挥装机人员(ConcreteBuilder)去构建组件;
  4. 将组件组装起来成小成需要的电脑(Product)

步骤1: 定义组装的过程(Builder):组装电脑的过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public  abstract class Builder {  

//第一步:装CPU
//声明为抽象方法,具体由子类实现
public abstract void BuildCPU()

//第二步:装主板
//声明为抽象方法,具体由子类实现
public abstract void BuildMainboard();

//第三步:装硬盘
//声明为抽象方法,具体由子类实现
public abstract void BuildHD();

//返回产品的方法:获得组装好的电脑
public abstract Computer GetComputer();
}

步骤2: 电脑城老板委派任务给装机人员(Director)

1
2
3
4
5
6
7
8
9
public class Director{
//指挥装机人员组装电脑
public void Construct(Builder builder){

builder. BuildCPU();
builder.BuildMainboard();
builder. BuildHD();
}
}

步骤3:创建具体的建造者(ConcreteBuilder):装机人员

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
//装机人员1
public class ConcreteBuilder extend Builder{
//创建产品实例
Computer computer = new Computer();

//组装产品
@Override
public void BuildCPU(){
computer.Add("组装好CPU")
}

@Override
public void BuildMainboard(){
computer.Add("组装好主板")
}

@Override
public void BuildHD(){
computer.Add("组装好硬盘")
}

//返回组装成功的电脑
@Override
public Computer GetComputer(){
return computer
}
}

//装机人员2
public class ConcreteBuilder2 extend Builder{
//创建产品实例
Computer computer = new Computer();

//组装产品
@Override
public void BuildCPU(){
computer.Add("组装垃圾CPU")
}

@Override
public void BuildMainboard(){
computer.Add("组装垃圾主板")
}

@Override
public void BuildHD(){
computer.Add("组装垃圾硬盘")
}

//返回组装成功的电脑
@Override
public Computer GetComputer(){
return computer
}
}

步骤4:定义具体产品类(Product):电脑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Computer{

//电脑组件的集合
private List<String> parts = new ArrayList<String>();

//用于将组件组装到电脑里
public void Add(String part){
parts.add(part);
}

public void Show(){
for (int i = 0;i<parts.size();i++){
System.out.println(“组件”+parts.get(i)+“装好了”);
}
System.out.println(“电脑组装完成,请验收”);
}
}

步骤5:客户端调用-小成到电脑城找老板买电脑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Builder Pattern{
public static void main(String[] args){

//逛了很久终于发现一家合适的电脑店
//找到该店的老板和装机人员
Director director = new Director();
Builder builder = new ConcreteBuilder()// Builder builder = new ConcreteBuilder2() ;

//沟通需求后,老板叫装机人员去装电脑
director.Construct(builder);

//装完后,组装人员搬来组装好的电脑
Computer computer = builder.GetComputer();

//组装人员展示电脑给小成看
computer.Show();
}
}

使用场景

  • 需要生成的产品对象有复杂的内部结构,这些产品对象具备共性;

  • 隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品。

优点

  • 易于解耦
    将产品本身与产品创建过程进行解耦,可以使用相同的创建过程来得到不同的产品。也就说细节依赖抽象。
  • 易于精确控制对象的创建
    将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰
  • 易于拓展
    增加新的具体建造者无需修改原有类库的代码,易于拓展,符合“开闭原则“。

缺点

  • 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似;如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。

  • 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。


行为型模式

  • 不仅仅关注类和对象的结构,而且重点关注它们之间的相互作用。

模板方法模式(Template Method Pattern)

  • 定义一个操作中的算法的框架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
  • 抽象模板中包含三种类型的方法: 基本方法模板方法钩子方法(Hook Method)
  • 基本方法——基本方法也叫做基本操作,是由子类实现的方法,并且在模板方法被调用。
  • 模板方法——核心方法,不允许子类重写,所以都会加上final修饰符,可以有一个或几个,一般是一个具体方法框架,按照固定的流程对基本方法的调度
  • 钩子方法——为了让模板方法的执行结果的更好地适应因外界条件改变。比如说银行办理业务为例,办理业务是个模板方法,普通人要经历排队、取号、等待、办理四个基本流程,而Vip则不需要排队、取号、等待,那么在设计的时候我们的抽象模板类需要考虑到,于是乎你得需要在模板方法各基本方法调用之前增加条件判断,那么用于设置这个条件的方法就是,钩子方法(Hook Method),钩子方法也可以是抽象的还可以由子类的一个方法返回值决定公共部分的执行结果

实现

  • 定义抽象模板类
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
public abstract class AbstractClass {
//基本方法1
protected abstract void doOneStep();
//基本方法2
protected abstract void doSecStep();
//基本方法3
protected abstract void doThirdStep();

//模板方法,为了避免被子类覆写改变模板方法的算法骨架一般使用final修饰,可以有N个模板方法
public final void work(){
/*
* 调用基本方法,完成相关的逻辑
*/
if(oneStepNeedRun){//钩子方法控制基本方法是否执行
this.doOneStep();
}
this.doSecStep();

this.doThirdStep();
}

//钩子方法它在抽象类中不做事或者是默认的事情,子类可以选择覆盖它,可以有N个
protected boolean oneStepNeedRun(){
return true;
}
}
  • 继承抽象模板类实现具体模板类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public class ConcreteClass extends AbstractClass {
    //实现基本方法
    protected void doOneStep() {
    //业务逻辑处理
    }
    protected void doSecStep() {
    //业务逻辑处理
    }
    protected void doThirdStep() {
    //业务逻辑处理
    }

    }

调用

1
public class TemplateMethod {    public static void main(String[] args) {        AbstractClass obj = new ConcreteClass();//多态构建        //调用模板方法        obj.work();    }}

实例讲解

  • 背景:直播流程,需要集成多家直播SDK
  • 用户看直播是有一套固定的模板流程的:登录—进入房间—获取音视频流—观看—停止音视频流—退出房间 虽然两套SDK每一个步骤的实现方式不同,但是基本都是遵循同一套流程
  1. 定义直播模板类

    1
    public abstract class LivePlay {    //模板方法    public final void seeLivePlay() {        login();        openRoom();        startAudioAndVideoStream();        pushVideoStream();        stopAudioAndVideoStream();        closeRoom();    }    //实体方法,这个方法实现通用的业务逻辑    private void login() {        System.out.println("用户登录");    }        /*抽象方法*/    //打开房间    public abstract void openRoom();    //打开音视频流    public abstract void startAudioAndVideoStream();    //关闭音视频流    public abstract void stopAudioAndVideoStream();    //关闭房间    public abstract void closeRoom();    /*钩子方法,可以被需要的子类overwrite*/    //旁路推流,可以通过视频链接在浏览器中查看视频    public void pushVideoStream() {    }}
  1. 定义具体的实体类,根据情况overwrite相应的抽象方法和钩子方法。

    ```java//腾讯直播类public class TencentLivePlay extends LivePlay  {    @Override    public void openRoom() {        System.out.println("腾讯打开房间");    }    @Override    public void startAudioAndVideoStream() {        System.out.println("腾讯打开音视频流");    }    @Override    public void stopAudioAndVideoStream() {        System.out.println("腾讯关闭音视频流");    }    @Override    public void closeRoom() {        System.out.println("腾讯关闭房间");    }    //覆写钩子方法,提供旁路推流功能    @Override    public void pushVideoStream() {        super.pushVideoStream();        System.out.println("腾讯进行旁路推流");    }}```
    
    1
    //金山直播类public class JinShanLivePlay extends LivePlay  {    @Override    public void openRoom() {        System.out.println("金山打开房间");    }    @Override    public void startAudioAndVideoStream() {        System.out.println("金山打开音视频流");    }    @Override    public void stopAudioAndVideoStream() {        System.out.println("金山关闭音视频流");    }    @Override    public void closeRoom() {        System.out.println("金山关闭房间");    }}
  1. 客户端调用
    我们根据后端返回的结果来决定使用哪家的SDK

    1
    public static void main(String[] args) {                //此处省略若干代码         ...        LivePlay tencentLive=new TencentLivePlay();        tencentLive.seeLivePlay();                System.out.println("");                LivePlay jinShanLive=new JinShanLivePlay();        jinShanLive.seeLivePlay();    }

使用场景

  • 多个子类有公有的方法,并且逻辑基本相同时。
  • 重要、复杂的算法,可以把核心算法设计为模板方法,周边的相关细节功能则由各个 子类实现。
  • 重构时,模板方法模式是一个经常使用的模式,把相同的代码抽取到父类中,然后通过钩子方法约束其行为。

优点

  • 主要是提高了代码的复用度,而且很好的符合的“开闭原则”。

缺点

  • 设计模式的通病:类增多了
  • 调用控制反转:一般情况下,程序的执行流是子类调用父类的方法,模板方法模式使得程序流程变成了父类调用子类方法,这个使得程序比较难以理解和跟踪

设计模式原则

  • 单一职责 : 类要职责单一
  • 里氏替换 : 不要破坏继承体系
  • 依赖倒置 : 面向接口编程
  • 接口隔离 : 接口设计要精简单一
  • 迪米特 : 降低耦合
  • 开闭原则 : 对扩展开放,对修改关闭