前面已经说过线性表类型的结构在进行插入和删除操作时要移动大量元素,导致时间复杂度高。
链表中,每一数据元素需要存储数据信息之外,还要存储它的后继元素的内存地址。
心之所向 无问东西
线性表(List):零个或多个数据元素的有限序列
线性表的相邻元素之间存在着序偶关系。如用(a1,…,ai-1,ai,ai+1,…,an)表示一个顺序表,则表中ai-1领先于ai,ai领先于ai+1,称ai-1是ai的直接前驱元素,ai+1是ai的直接后继元素。
元素个数有限,元素之间有顺序,第一个元素无前驱,最后一个元素无后继。顺序存储结构的线性表,指的是地址连续的存储单元依次存储线性表的数据元素。
Operation
在java语言中,实例化对象的方式大多使用new关键字,但是在某些情况下使用new关键字来实例化对象并不是最好的选择。
比如:某个类型的创建需要一系列初始值的计算工作,或者需要首先创建其他的辅助对象。那么类型的创建就不是单一的操作,而是一系列操作!客户端并不关心对象其内部的复杂运作,只是需要一个简单入口可以获得自己想要的实例。
为创建对象提供过渡接口,以便将创建对象的内部调用屏蔽起来,达到提高灵活性的目的。工厂模式可以分为三类:
一个抽象产品类—>多个具体产品类
一个抽象工厂类—>多个具体工厂类
每个具体工厂只能创建一个具体的产品(一对一关系)
多个抽象产品类—>每种抽象产品对应多个具体产品
一个抽象工厂类—>多个具体工厂类
每个具体工厂可以创建多个具体的产品(一对多关系)
生产thinkpad的内部过程必然是复杂的,但是经过工厂模式后都被屏蔽了起来。工厂是核心,应该包含一定的业务判断和逻辑用来选择进行创建的产品。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
42public abstract class Computer {
public Computer(){};
}
public class ThinkPad_E450 extends Computer {
public ThinkPad_E450(){
System.out.println("生产ThinkPad_E450");
}
}
public class ThinkPad_E460 extends Computer {
public ThinkPad_E460(){
System.out.println("生产ThinkPad_E460");
}
}
public class SimpleFactory {
public Computer createComputer(int type) {
switch (type) {
case 450:
return new ThinkPad_E450();
case 460:
return new ThinkPad_E460();
default:
break;
}
return null;
}
}
public class App {
public static void main(String[] args){
SimpleFactory factory = new SimpleFactory();
factory.createComputer(450);
}
}
分析代码:对于产品而言,如果需要新增产品那么创建Computer的子类即可,但是对于工厂则要修改业务逻辑来适配新产品的创建,这显然违背好的设计原则。在实际的生产中产品的形态可能是一种树状结构,就更加复杂了。
我们将工厂类也定义成接口,每增加一种产品类型就增加一个工厂的实现来适配对应的产品创建,这样工厂的设计就可以扩展而不是去修改原来的代码!
针对每种产品适配一个工厂,UML如下。代码见My Github - 设计模式
工厂方法模式仿佛已经很完美的对对象的创建进行了包装,使得客户程序中仅仅处理抽象产品角色提供的接口,但使得对象的数量成倍增长。
当产品种类非常多时,会出现大量的与之对应的工厂对象。
抽象工厂是工厂方法模式的升级版,它用来创建一组相互依赖的对象。比如每个抽象产品角色都包含两个具体产品,并且它们之间是相互依赖的。在调用工厂暴露的方法创建产品时,会同时创建相互依赖的对象来构建一个完整的产品。而不是单个创建然后组装。详见:抽象工厂模式
单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
Singleton类,定义一个getInstance静态方法,允许客户访问它的唯一实例。
1 | public class Singleton { |
1 | Singleton s1 = Singleton.getInstance(); |
但是懒汉式的单例模式并不是线程安全的,在多线程并发的情况下可能会出现多个实例。要实现线程安全,要对getInsance方法进行改造使懒汉式变得线程安全。
1 | public static synchronized Singleton getInstance_1(){ |
虽然多线程下是安全的,但是方法的整个事务判断全部被同步,这种写法效率不高!
1 | public static Singleton getInstance_2(){ |
双重检查模式先判断实例是否存在,不存在再进行加锁处理。相比上一种写法提高了效率。
1 | public class Singleton { |
相比上两种写法,效率要高!
1 | public class SingletonA { |
饿汉式单例在类创建的同时就创建了一个静态的实例变量,所以天生是线程安全的!
面向切面编程可以说是面向对象编程的补充和完善。OOP引入封装、继承、多态的概念来建立一种层次结构,但是OOP并不适合定义横向的关系。例如日志功能,日志往往是横向地散布在所有对象中,且与对象的核心功能毫无关系。这种散布在各处的无关代码被称为横切,在OOP设计中,它导致了大量代码的重复,复用性低。
more >>
Spring对jdbc技术提供了很好的支持:
体现在:
缺失模块。
1、请确保node版本大于6.2
2、在博客根目录(注意不是yilia根目录)执行以下命令:
npm i hexo-generator-json-content --save
3、在根目录_config.yml里添加配置:
jsonContent: meta: false pages: false posts: title: true date: true path: true text: false raw: false content: false slug: false updated: false comments: false link: false permalink: false excerpt: false categories: false tags: true