目录
UML图
什么是UML图
UML-Unified Modeling Language 统一建模语言,又称标准建模语言。是用来对软件密集系统进行可视化建模的一种语言。UML的定义包括UML语义和UML表示法两个元素。
UML是在开发阶段,说明、可视化、构建和书写一个面向对象软件密集系统的制品的开放方法。最佳的应用是工程实践,对大规模,复杂系统进行建模方面,特别是在软件架构层次,已经被验证有效。统一建模语言(UML)是一种模型化语言。模型大多以图表的方式表现出来。一份典型的建模图表通常包含几个块或框,连接线和作为模型附加信息之用的文本。这些虽简单却非常重要,在UML规则中相互联系和扩展。
UML图的作用
UML的目标是以面向对象图的方式来描述任何类型的系统,具有很宽的应用领域。其中最常用的是建立软件系统的模型,但它同样可以用于描述非软件领域的系统,如机械系统、企业机构或业务过程,以及处理复杂数据的信息系统、具有实时要求的工业系统或工业过程等。总之,UML是一个通用的标准建模语言,可以对任何具有静态结构和动态行为的系统进行建模,而且适用于系统开发的不同阶段,从需求规格描述直至系统完成后的测试和维护。
UML图的特点
(1)UML统一了各种方法对不同类型的系统、不同开发阶段以及不同内部概念的不同观点,从而有效的消除了各种建模语言之间不必要的差异。它实际上是一种通用的建模语言,可以为许多面向对象建模方法的用户广泛使用。
(2)UML建模能力比其它面向对象建模方法更强。它不仅适合于一般系统的开发,而且对并行、分布式系统的建模尤为适宜。
(3)UML是一种建模语言,而不是一个开发过程。
UML的主要模型
在UML系统开发中有三个主要的模型:
功能模型
从用户的角度展示系统的功能,包括用例图。
对象模型
采用对象、属性、操作、关联等概念展示系统的结构和基础,包括类图、对象图、包图。
动态模型
UML图的几种关系
U在UML类图中,常见的有以下几种关系: 泛化(Generalization), 实现(Realization),关联(Association),聚合(Aggregation),组合(Composition),依赖(Dependency)
1. 泛化(Generalization)
【泛化关系】:是一种继承关系,表示一般与特殊的关系,它指定了子类如何特化父类的所有特征和行为。例如:老虎是动物的一种,即有老虎的特性也有动物的共性。
【箭头指向】:带三角箭头的实线,箭头指向父类
2. 实现(Realization)
【实现关系】:是一种类与接口的关系,表示类是接口所有特征和行为的实现.
【箭头指向】:带三角箭头的虚线,箭头指向接口
3. 关联(Association)
【关联关系】:是一种拥有的关系,它使一个类知道另一个类的属性和方法;如:老师与学生,丈夫与妻子关联可以是双向的,也可以是单向的。双向的关联可以有两个箭头或者没有箭头,单向的关联有一个箭头。
【代码体现】:成员变量
【箭头及指向】:带普通箭头的实心线,指向被拥有者
上图中,老师与学生是双向关联,老师有多名学生,学生也可能有多名老师。但学生与某课程间的关系为单向关联,一名学生可能要上多门课程,课程是个抽象的东西他不拥有学生。
下图为自身关联:
4. 聚合(Aggregation)
【聚合关系】:是整体与部分的关系,且部分可以离开整体而单独存在。如车和轮胎是整体和部分的关系,轮胎离开车仍然可以存在。
聚合关系是关联关系的一种,是强的关联关系;关联和聚合在语法上无法区分,必须考察具体的逻辑关系。
【代码体现】:成员变量
【箭头及指向】:带空心菱形的实心线,菱形指向整体
5. 组合(Composition)
【组合关系】:是整体与部分的关系,但部分不能离开整体而单独存在。如公司和部门是整体和部分的关系,没有公司就不存在部门。
组合关系是关联关系的一种,是比聚合关系还要强的关系,它要求普通的聚合关系中代表整体的对象负责代表部分的对象的生命周期。
【代码体现】:成员变量
【箭头及指向】:带实心菱形的实线,菱形指向整体
6. 依赖(Dependency)
【依赖关系】:是一种使用的关系,即一个类的实现需要另一个类的协助,所以要尽量不使用双向的互相依赖.
【代码表现】:局部变量、方法的参数或者对静态方法的调用
【箭头及指向】:带箭头的虚线,指向被使用者
各种关系的强弱顺序:
泛化 = 实现 > 组合 > 聚合 > 关联 > 依赖
下面这张UML图,比较形象地展示了各种类图关系:
List接口
特点:元素有序,且可重复
遍历:下标,foreach,迭代器
扩容:初始容量10,负载因子0.5,扩容增量0.5倍
新容量 = 原容量 + 原容量 * 0.5 , 如 ArrayList的容量为10,一次扩容后是容量为15
List的实现类
1.ArrayList
- 简单数据结构,超出容量自动扩容,动态数组
- ArrayList的扩容机制是效率和空间的之间的平衡,
- 内部实现是基于基础的对象数组的
- 不适合随机增加或删除(有位移现象)
- 适用于不确定数据的最大个数的情况
- 随机访问快、遍历快
- 线程不安全(在作为类的成员变量时)
2.LinkedList
- LinkedList提供额外的get,remove,insert方法在LinkedList的首部或尾部
- LinkedList可被用作堆栈(stack)【包括了push,pop方法】,队列(queue)或双向队列(deque)
- 以双向链表实现,链表无容量限制,允许元素为null,线程不安全
- 适合做随机的增加或删除,因为链表结构在增加删除时不会出现位移现象
3.Vector
线程安全,但是并行性能慢(因为上锁了),不建议使用
4.CopyOnWriteArrayList
- 写时复制
- 线程安全
- (版本的)最终一致性,无法做到实时版本一致
- 比Vector性能高
- 适合于读多,写少的场景
- 实现了List接口,使用方式与ArrayList类似
- 写时复制出一个新的数组,完成插入、修改或者移除操作后将新数组赋值给原来的数组
使用ArrayList中remove方法的注意点
remove特性:
- 传入整数类型时删除下标
- 传入对象类型时删除对应的元素(如Integer.parseInt(null))
数据准备工作:为方便演示,需要有紧挨在一起的两个或多个相同的元素
List<Integer> list=new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(3);
list.add(3);
list.add(4);
使用ArrayList中remove方法的几种不同的写法:
错误写法示例
for(int i=0;i<list.size();i++){
if(list.get(i)==3) list.remove(i);//list.get(i)得到下标为i的元素
}
错误原因:
ArrayList在增加和删除时有位移现象,当两个一样的元素3相邻时,第一个3在判断并删除后,第二个3及其后面的所有元素的下标都会向前移动一位,这样第二个3就到了第一个3下标所在的位置,但是指针已经判断过第一个3所在位置的元素是否为3了,故不会删除掉第二个3。
for(Integer i:list){
if(i==3) list.remove(i);
}
错误原因:
因为ArrayList中有一个变量(modCount=原数组的元素个数)还在内部封装了一个内部类(Itr),这个内部类实现了迭代器,当使用foreach方法遍历时,使用的是ArrayList内部类的迭代器,其中内部类中定义了一个改变次数的变量(expectedModCount),这个变量被赋值为外部modcount的值,当使用内部类(Itr)发生增加或者修改操作时,抛出异常,其目的是阻止ArrayList长度发生改变。
简而言之,就是不推荐使用foreach进行集合的增加和删除操作,它更适合用来遍历数据。
正确写法示例
for(int i=0;i<list.size();i++){
if(list.get(i)==3) list.remove(i--);
}
正确原因:
使用了i--,即在进行删除之后指针会向前移一位,再回到删除过的下标位置进行判断,而这样就避免了因为ArrayList的位移现象所导致的判断遗漏。
注意:不可使用--i,因为--i会在remove方法在删除之前执行
for(int i=list.size()-1;i>=0;i--){
if(list.get(i)==3){
list.remove(i);
}
}
正确原因:
使用了从集合中的最后一位元素向第一位元素方向进行遍历的倒序遍历方法,这样即使ArrayList的位移现象发生也无法对删除产生影响。
最后一种写法:ArrayList集合在进行删除、增加等操作时,要考虑其动态位移的特性,推荐使用迭代器,会比较安全
Iterator<Integer> it=list.iterator();
while(it.hasNext()){
if(it.next()==3){
it.remove();
}
}
注意:上述代码的it.remove不要写成list.remove(i)看
本篇文章关于UML的部分基础来自百度百科,关于UML图的几种关系的原文章来自http://www.uml.org.cn/oobject/201609062.asp
本篇文章就到此结束了拜拜(づ ̄ 3 ̄)づ