0%

设计模式

Summary

设计模式是面向对象设计中反复出现的问题的解决方案。这个术语在1990年代由Erich Gamma等人从建筑设计领域引入到计算机科学中来。算法不是设计模式因为算法致力于解决问题而非设计问题。设计模式通常提供一种讨论软件设计的公共语言,使得熟练设计者的设计经验可以被初学者和其他设计者掌握。*设计模式还为软件重构提供了目标。

History

Erich Gamma与Richard Helm, Ralph Johnson ,John Vlissides合作出版了Design Patterns - Elements of Reusable Object-Oriented Software 一书,在此书中共收录了23个设计模式。这四位作者在软件开发领域里也以他们的匿名著称Gang of Four(四人帮,简称GoF),并且是他们在此书中的协作导致了软件设计模式的突破。

Pattern Format

尽管名称和顺序在不同的资料中各有不同,描述模式的格式大致分为以下四个主要部分:
模式名称(Pattern Name):每一个模式都有自己的名字,模式的名字使得我们可以讨论我们的设计。
问题(Problem):在面向对象的系统设计过程中反复出现的特定场合,它导致我们采用某个模式。
解决方案(Solution):上述问题的解决方案,其内容给出了设计的各个组成部分,它们之间的关系、职责划分和协作方式。
效果(Consequence):采用该模式对软件系统其他部分的影响,比如对系统的扩充性、可移植性的影响。影响也包括负面的影响。
别名(Also Known As):一个模式可以有超过一个以上的名称。这些名称应该要在这一节注明。
动机(Motivation):该模式应该利用在哪种情况下是本节提供的方案(包括问题与来龙去脉)的责任。
应用(Applicability)
结构(Structure):这部分常用类图与互动图阐述此模式。
参与者(Participants):这部分提供一份本模式用到的类与物件清单,与它们在设计下扮演的角色。
合作(Collaboration):描述在此模式下,类与物件间的互动。
结果(Consequences):这部分应描述使用本模式後的结果、副作用、与交换(trade-off)
实现(Implementaion):这部分应描述实现该模式、该模式的部分方案、实现该模式的可能技术、或者建议实现模式的方法。
例程(Sample Code):示范程式。
已知应用(Known Uses):业界已知的实做范例。
相关模式(Related Patterns):这部分包括其他相关模式,以及与其他类似模式的不同。

Mode

模式列表

  • 基础模式
  • 委托模式
  • 接口模式
  • 代理模式

创建模式

  • 抽象工厂模式(Abstract Factory) ,提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
  • 生成器模式 (Builder),将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
  • 工厂方法模式(Factory Method) ,定义一个用于创建对象的接口,让子类决定将哪一个类实例化。Factory Method使一个类的实例化延迟到其子类。
  • 原型模式 (Prototype) ,用原型实例指定创建对象的种类,并且通过拷贝这个原型来创建新的对象。
  • 单例模式(Singleton),保证一个类仅有一个实例,并提供一个访问它的全局访问点。

结构模式

  • 适配器模式 (Adapter) ,将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
  • 桥接模式(Bridge) ,将抽象部分与它的实现部分分离,使它们都可以独立地变化。
  • 组合模式(Composite) ,将对象组合成树形结构以表示“部分-整体”的层次结构。它使得客户对单个对象和复合对象的使用具有一致性。
  • 容器模式
  • 修饰模式 (Decorator) ,动态地给一个对象添加一些额外的职责。就扩展功能而言, 它比生成子类方式更为灵活。
  • 扩展性模式
  • 外观模式
  • 享元模式
  • 管道与过滤器模式
  • 代理模式(Proxy) ,为其他对象提供一个代理以控制对这个对象的访问。

行为模式

  • 责任链模式 (Chain of Responsibility) ,为解除请求的发送者和接收者之间耦合,而使多个对象都有机会处理这个请求。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它。
  • 命令模式 (Command) ,将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可取消的操作。
  • 柯里化模式
  • 事件监听器模式
  • 解释器模式
  • 迭代器模式
  • 中介者模式
  • 备忘录模式 (Memento) ,在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到保存的状态。
  • 观察者模式(Observer) ,定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动刷新。
  • 状态模式 (State) ,允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它所属的类。
  • 策略模式 (Strategy) ,定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法的变化可独立于使用它的客户。
    模板方法模式
  • 访问者模式 (Visitor),表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
  • 层次访问者模式

并发模式

  • 模式 Action at a distance
  • 模式 Balking
  • 模式 Guarded suspension
  • 模式 Scheduler
  • 模式 Read write lock
  • 模式 Double checked locking
  • 模式 Disable job requests while running job

实时模式

  • 模式 Scheduled task
  • 模式 User interface
  • 模式 Disable job requests while running job

其他

  • 模型—视图—控制器模式

Day03 - 移除元素

给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度。

不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

示例 1:

给定 nums = [3,2,2,3], val = 3,函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中超出新长度后面的元素.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution {
public int removeElement(int[] nums, int val) {
int res = 0;

for (int i = 0; i < nums.length; i++) {
if (nums[i] != val) {
nums[res] = nums[i];
res++;
}
}

return res;
}
}

/**
执行用时 :0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗 :38.1 MB, 在所有 Java 提交中击败了5.05%的用户
*/

res记录新数组长度,遍历一遍数组满足条件则在相应位置赋值。

Reference
https://leetcode-cn.com/problems/remove-element

Day02 - 删除排序数组的重复项

给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。

不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。

示例1

给定数组 nums = [1,1,2],函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2。你不需要考虑数组中超出新长度后面的元素。`

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
class Solution {
public int removeDuplicates(int[] nums) {
int length;

if (nums.length == 0) {
return 0;
}

length = 1;

for (int i = 0, j = 1; i < nums.length; i++) {
while (j < nums.length && nums[j] == nums[i]) {
j++;
}

if (j >= nums.length)
break;

if (nums[j] != nums[i]) {
nums[i + 1] = nums[j];
length++;
}
}

return length;
}
}

/**
执行用时 :1 ms, 在所有 Java 提交中击败了99.89%的用户
*/

length 记录新数组长度,只需要在原数组中遍历一次与第 i 项比较若不同则将第 j 项赋给第 i+1 项。

Reference
https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/

Day01 - 两数之和

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。

你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。

示例:

给定 nums = [2, 7, 11, 15], target = 9

因为 nums[0] + nums[1] = 2 + 7 = 9所以返回 [0, 1]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] two = new int[2];
for (int i = 0; i < nums.length; i++) {
for (int j = nums.length - 1; j > i; j--) {
if (nums[i] + nums[j] == target) {
two[0] = i;
two[1] = j;
return two;
}
}
}
return null;
}
}

Reference
https://leetcode-cn.com/problems/two-sum

Welcome to GitHub Pages

You can use the editor on GitHub to maintain and preview the content for your website in Markdown files.

Whenever you commit to this repository, GitHub Pages will run Jekyll to rebuild the pages in your site, from the content in your Markdown files.

Markdown

Markdown is a lightweight and easy-to-use syntax for styling your writing. It includes conventions for

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Syntax highlighted code block

# Header 1
## Header 2
### Header 3

- Bulleted
- List

1. Numbered
2. List

**Bold** and _Italic_ and `Code` text

[Link](url) and ![Image](src)

For more details see GitHub Flavored Markdown.

Jekyll Themes

Your Pages site will use the layout and styles from the Jekyll theme you have selected in your repository settings. The name of this theme is saved in the Jekyll _config.yml configuration file.

Support or Contact

Having trouble with Pages? Check out our documentation or contact support and we’ll help you sort it out.