0%

生成器模式是一种创建型设计模式, 使你能够分步骤创建复杂对象。 该模式允许你使用相同的创建代码生成不同类型和形式的对象。

阅读全文 »

面向对象思想

三大特性

封装

利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体。数据被保护在抽象数据类型内部,尽可能隐藏内部的细节,只保留一些对外交互的接口使其与外部发生联系。

优点:

  • 减少耦合:可以独立开发、测试、优化、修改、调试。因此也可以减轻维护的负担。
  • 有效的调节性能:可以通过剖析来确定哪些模块影响了系统的性能
  • 提高软件的可重用性
  • 降低了构建大型系统的风险:即使整个系统不可用,但是这些独立的模块却有可能是可用的

继承

继承实现了 IS-A 关系(IS-A是一种继承关系,has-A是一种包含关系,例如一个类中包含另一个类)

继承应该遵循里氏替换原则,子类对象必须能够替换掉所有父类对象

多态

多态分为编译时多态和运行时多态:

  • 编译时多态主要指方法的重载 模板
  • 运行时多态指程序中定义的对象引用所指向的具体类型在运行期间才确定

运行时多态有三个条件:

  • 继承

  • 覆盖(重写)

  • 向上转型

    类图

设计原则

单一责任原则

让一个类只负责一件事,当这个类需要做过多事情的时候,就需要分解这个类。如果一个类承担的职责过多,就等于把这些职责耦合在了一起,一个职责的变化可能会削弱这个类完成其它职责的能力。

开放封闭原则

该原则要求在添加新功能时不需要修改代码。符合开闭原则最典型的设计模式是装饰者模式,它可以动态地将责任附加到对象上,而不用去修改类的代码。

里氏替换原则

子类对象必须能够替换掉所有父类对象。继承是一种 IS-A 关系,子类需要能够当成父类来使用,并且需要比父类更特殊。如果不满足这个原则,那么各个子类的行为上就会有很大差异,增加继承体系的复杂度。

接口分离原则

不应该强迫客户依赖于它们不用的方法。因此使用多个专门的接口比使用单一的总接口要好。

依赖倒置原则

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

相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建起来的架构比以细节为基础搭建起来的架构要稳定的多。在java中,抽象指的是接口或者抽象类,细节就是具体的实现类使用接口或者抽象类的目的是制定好规范和契约,而不去涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成。

依赖倒置原则的核心思想是面向接口编程

依赖于抽象意味着:

  • 任何变量都不应该持有一个指向具体类的指针或者引用;
  • 任何类都不应该从具体类派生;
  • 任何方法都不应该覆写它的任何基类中的已经实现的方法

其他设计原则

除了上述的经典原则,在实际开发中还有下面这些常见的设计原则。

迪米特法则

迪米特法则又叫作最少知识原则(Least Knowledge Principle,简写 LKP),就是说一个对象应当对其他对象有尽可能少的了解,不和陌生人说话

合成复用原则

尽量使用对象组合,而不是通过继承来达到复用的目的。

共同封闭原则

一起修改的类,应该组合在一起(同一个包里)。如果必须修改应用程序里的代码,我们希望所有的修改都发生在一个包里(修改关闭),而不是遍布在很多包里

稳定抽象原则

最稳定的包应该是最抽象的包,不稳定的包应该是具体的包,即包的抽象程度跟它的稳定性成正比

稳定依赖原则

包之间的依赖关系都应该是稳定方向依赖的,包要依赖的包要比自己更具有稳定性。

HTTPS

参考链接

参考链接

HTTP 有以下安全性问题:

  • 使用明文进行通信,内容可能会被窃听;
  • 不验证通信方的身份,通信方的身份有可能遭遇伪装;
  • 无法证明报文的完整性,报文有可能遭篡改

HTTPS 并不是新协议,而是让 HTTP 先和 SSL(Secure Sockets Layer)通信,再由 SSL 和 TCP 通信,也就是说 HTTPS 使用了隧道进行通信。通过使用 SSL,HTTPS 具有了加密(防窃听)、认证(防伪装)和完整性保护(防篡改)

image-20210520171309580

HTTPS 有以下三个要点

  • 加密
  • 数据完整性
  • 身份验证:通过认证实现

流程如下图:

img

加密

对称加密

对称密钥加密(Symmetric-Key Encryption),加密和解密使用同一密钥。

  • 优点:运算速度快;
  • 缺点:无法安全地将密钥传输给通信方。

例如 AES加密算法,加密就是 将 明文和密钥 通过一个加密函数映射得到密文。解密就是函数的逆映射。AES为分组密码,分组密码也就是把明文分成一组一组的,每组长度相等,每次加密一组数据,直到加密完整个明文。

非对称加密

非对称密钥加密,又称公开密钥加密(Public-Key Encryption),加密和解密使用不同的密钥。公开密钥所有人都可以获得,通信发送方获得接收方的公开密钥之后,就可以使用公开密钥进行加密,接收方收到通信内容后使用私有密钥解密。

非对称密钥除了用来加密,还可以用来进行签名。因为私有密钥无法被其他人获取,因此通信发送方使用其私有密钥进行签名,通信接收方使用发送方的公开密钥对签名进行解密,就能判断这个签名是否正确。

  • 优点:可以更安全地将公开密钥传输给通信发送方;
  • 缺点:运算速度慢。
image-20201208203759099

例如 RSA算法,它的安全性基于 整数分解,使用两个超大素数的乘积作为生成密钥的材料

HTTPS 采用的加密方式

上面提到对称密钥加密方式的传输效率更高,但是无法安全地将密钥 Secret Key 传输给通信方。而非对称密钥加密方式可以保证传输的安全性,因此我们可以利用非对称密钥加密方式将 Secret Key 传输给通信方。HTTPS 采用混合的加密机制,正是利用了上面提到的方案:

  • 使用非对称密钥加密方式,传输对称密钥加密方式所需要的 Secret Key,从而保证安全性;
  • 获取到 Secret Key 后,再使用对称密钥加密方式进行通信,从而保证效率。(下图中的 Session Key 就是 Secret Key)

完整性保护

SSL 提供报文摘要功能来进行完整性保护。

  • HTTP 也提供了 MD5 报文摘要功能,但不是安全的。例如报文内容被篡改之后,同时重新计算 MD5 的值,通信接收方是无法意识到发生了篡改。
  • HTTPS 的报文摘要功能之所以安全,是因为它结合了加密和认证这两个操作。试想一下,加密之后的报文,遭到篡改之后,也很难重新计算报文摘要,因为无法轻易获取明文。

MD5 全程 密码哈希算法(cryptographic hash algorithm),MD5 可用于从任意长度的字符串创建 128 位字符串值,MD5 最常用于验证文件的完整性。除了MD5加密算法外,TLS 里用的是 SHA-2

认证

通过使用 证书 来对通信方进行认证。数字证书认证机构(CA,Certificate Authority)是客户端与服务器双方都可信赖的第三方机构。

服务器的运营人员向 CA 提出公开密钥的申请,CA 在判明提出申请者的身份之后,会对已申请的公开密钥做数字签名,然后分配这个已签名的公开密钥,并将该公开密钥放入公开密钥证书后绑定在一起。进行 HTTPS 通信时,服务器会把证书发送给客户端。客户端取得其中的公开密钥之后,先使用数字签名进行验证,如果验证通过,就可以开始通信了。

签名的过程可以理解为 CA 机构使用私钥对签名进加密,同时对签名的明文使用 数据摘要算法(散列算法)将签名压缩为一个固定的长度的数据,这个就是上面所说的完整性保护中用的方法。客户端收到证书后,需要使用 公钥CA的公钥对 签名解密然后使用同样的散列函数对 解密后的签名进行压缩 再和 给定的进行对比,如果一致 说明签名在加密后没有被篡改过,是合法的。

HTTPS 的安全性

不是绝对安全的,可以通过中间人攻击。

什么是中间人攻击

中间人攻击是指攻击者与通讯的两端分别创建独立的联系,并交换其所收到的数据,使通讯的两端认为他们正在通过一个私密的连接与对方直接对话,但事实上整个会话都被攻击者完全控制。

HTTPS 使用了 SSL 加密协议,是一种非常安全的机制,目前并没有方法直接对这个协议进行攻击,一般都是在建立 SSL 连接时,拦截客户端的请求,利用中间人获取到 CA证书、非对称加密的公钥、对称加密的密钥;有了这些条件,就可以对请求和响应进行拦截和篡改。

image.png

https 是如何防止中间人攻击的

https 无法防止中间人攻击,只有做证书固定ssl-pinning 或者 apk中预置证书做自签名验证可以防中间人攻击。具体的可以看这一篇文章。

HTTPS的缺点

  • 因为需要进行加密解密等过程,因此速度会更慢;
  • 需要支付证书授权的高额费用。

GET 和 POST 比较

作用

GET 用于获取资源,而 POST 用于传输实体主体。

参数

GET 和 POST 的请求都能使用额外的参数,但是 GET 的参数是以查询字符串出现在 URL 中,而 POST 的参数存储在实体主体中。不能因为 POST 参数存储在实体主体中就认为它的安全性更高,因为照样可以通过一些抓包工具(Fiddler)查看。

因为 URL 只支持 ASCII 码,因此 GET 的参数中如果存在中文等字符就需要先进行编码。例如 中文 会转换为 %E4%B8%AD%E6%96%87,而空格会转换为 %20。POST 参数支持标准字符集。

1
GET /test/demo_form.asp?name1=value1&name2=value2 HTTP/1.1
1
2
3
POST /test/demo_form.asp HTTP/1.1
Host: w3schools.com
name1=value1&name2=value2

安全

安全的 HTTP 方法不会改变服务器状态,也就是说它只是可读的。GET 方法是安全的,而 POST 却不是,因为 POST 的目的是传送实体主体内容,这个内容可能是用户上传的表单数据,上传成功之后,服务器可能把这个数据存储到数据库中,因此状态也就发生了改变。

安全的方法除了 GET 之外还有:HEAD、OPTIONS。

不安全的方法除了 POST 之外还有 PUT、DELETE。

幂等性

幂等的 HTTP 方法,同样的请求被执行一次与连续执行多次的效果是一样的,服务器的状态也是一样的。换句话说就是,幂等方法不应该具有副作用(统计用途除外)。

所有的安全方法也都是幂等的。

在正确实现的条件下,GET,HEAD,PUT 和 DELETE 等方法都是幂等的,而 POST 方法不是。

GET /pageX HTTP/1.1 是幂等的,连续调用多次,客户端接收到的结果都是一样的:

1
2
3
4
GET /pageX HTTP/1.1
GET /pageX HTTP/1.1
GET /pageX HTTP/1.1
GET /pageX HTTP/1.1

POST /add_row HTTP/1.1 不是幂等的,如果调用多次,就会增加多行记录:

1
2
3
POST /add_row HTTP/1.1   -> Adds a 1nd row
POST /add_row HTTP/1.1 -> Adds a 2nd row
POST /add_row HTTP/1.1 -> Adds a 3rd row

可缓存

如果要对响应进行缓存,需要满足以下条件:

  • 请求报文的 HTTP 方法本身是可缓存的,包括 GET 和 HEAD,但是 PUT 和 DELETE 不可缓存,POST 在多数情况下不可缓存的。
  • 响应报文的状态码是可缓存的,包括:200, 203, 204, 206, 300, 301, 404, 405, 410, 414, and 501。
  • 响应报文的 Cache-Control 首部字段没有指定不进行缓存

XMLHttpRequest

为了阐述 POST 和 GET 的另一个区别,需要先了解 XMLHttpRequest:

XMLHttpRequest 是一个 API,它为客户端提供了在客户端和服务器之间传输数据的功能。它提供了一个通过 URL 来获取数据的简单方式,并且不会使整个页面刷新。这使得网页只更新一部分页面而不会打扰到用户。XMLHttpRequest 在 AJAX 中被大量使用。

  • 在使用 XMLHttpRequest 的 POST 方法时,浏览器会先发送 Header 再发送 Data。但并不是所有浏览器会这么做,例如火狐就不会。
  • 而 GET 方法 Header 和 Data 会一起发送

位运算类题目

位运算的题目,常规的思路就是异或为0的规律做。

剑指 Offer 56 - II. 数组中数字出现的次数 II

这个题很巧妙。一个数组中一个数字出现了 N 次,只有一个出现了1次,找出这个出现一次的数,可以知道,出现N次那么对应的位的和一定为N的倍数。对于所有元素的某一位,可能是 0 2N 3N 4N… 或着 1 2N+1 3N+1 …

矩阵置零

O(m+n) 的方法很好实现。主要是 O(1) 的方法。O(m+n) 的方法思路是设置一个标记数组,用于标记哪些行和列需要被置0,现在要求空间复杂度为O(1) 用到了原地标注的方法,如果数组中某个位置的元素为0,那么这一行列的数全要置0,因此反正都要设置为0的,可以将该行列标号先记下来,用作标记数组,即原地标记,最后其他的行列0都置完了 再对这行列清0。这个思想在 O(1) 的hash 方法中见过,题目给定的数组中元素都是正数,那么就可以用负数来作为标记,从而使得空间复杂度为O(1)