UML(Unified Modeling Language,统一建模语言)建模是面向对象开发设计方法中的第一步,用UML来表达设计模式不仅方便了开发人员的交流,而且更加清晰、准确。UML定义了5类10种模型图,每种图都有其不同的目的,说明了不同实体集合之间的关系,如下表:
由于在后面设计模式的学习中会大量的用到类图,所以这里只对类图进行简单的介绍
UML类图中的基本元素符号
1. 类
类的UML图有3部分组成。
第一个部分是定义的类名,如果类名是用斜体字形表示,则表示该类是抽象类,否则就是具体的类。
第二部分是属性,第三部分是方法。在属性和方法之前均可附加一个访问权限修饰符。加号(+)代表public;减号(-)代表private;#代表protected;没有任何修饰符表示访问权限是友好的,修饰符为friendly,但是需注意在java中是没有friendly修饰符的。如果属性或方法具有下划线,则表明它是静态的。如果在一个类图中只想显示高层细节,那么下面的两部分信息(属性和方法)不是必要的。
2. 接口
第一部分是接口的名称,必须用斜体字表示,而且顶端要用<<interface>>来修饰;第二部分是常量;第三部分是方法。
3. 注释
类与类之间的关系
在UML类图中,类与类之间有以下几种常见的关系:泛化(Generalization)、实现(Realization)、依赖(Dependency)、关联(Association)和组合(Composition)
1. 泛化(继承)
泛化也就是通常所说的继承关系,也称“is a kind of”关系。泛化是对象间耦合度最大的一种关系,UML表示法如下:
2. 实现
如果一个类B实现一个接口A的功能,那么类B和类A的关系就是实现,UML表示法如下:
3. 依赖
如果B作为参数被A类在某个方法中使用,则A依赖于B,UML表示法如下:
java代码示例为:
public class Car {
}
public class Person {
private String name;
public void drive(Car car) {
}
}
4. 关联
如果A类中的成员变量是用B类声明的变量,即B类作为A类的一个属性存在,则A关联与B,UML类图如下:
java代码示例为:
public class B {
}
public class A {
private B b;
public B getB() {
return this.b;
}
public void setB(B b) {
this.b = b;
}
}
另外,除了上述的单向关联外,还有双向关联和自关联,UML类图如下:
双向关联:
自关联:
java代码示例为:
public class Mouse {
}
public class Computer {
private Mouse m;
public Mouse getM() {
return this.m;
}
public void setM(Mouse m) {
this.m = m;
}
}
5. 聚合
聚合关系是关联关系的一种(弱关联),与关联不同的是聚合体现的是整体和个体的关系,而关联体现的是两个处在同一层次的类之间的关系。这里的整体和个体是可以分离的,即个体可以独立于整体存在,例如电脑和鼠标,二者是一种“has-a”的关系。UML类图如下:
6. 组合
组合也是关联的一种(强关联),与聚合类似,同样体现的是整体和个体的关系,但这里的整体和个体是不可以分离的,即个体是整体的一部分,例如电脑和CPU。这种关系比聚合更强,是一种“contains-a”的关系,也称强聚合。一旦整体对象不存在,部分对象也不存在;同样部分对象不存在,整体对象也无法正常工作,部分和整体具有相同的生命周期。代码上表现为A类中的成员变量是用B类声明的变量,并且B对象在A对象创建时创建。UML类图如下:
java代码示例为:
public class CPU {
}
public class Computer {
private CPU c;
public Computer () {
c = new CPU();
}
}
实例分析——聊天系统登录模块
基于C/S的聊天系统登录模块功能描述:
用户通过登录页面(LoginForm)输入账号和密码,系统将输入的账号和密码与存储在数据库(User)表中的用户信息进行比较,验证用户输入是否正确,如果输入正确,则进入主界面(MainForm),否则提示“输入错误”。
该系统中类的说明表如下:
类名 | 说明 |
---|---|
LoginForm | 登录窗口(边界类) |
LoginBO | 登录业务逻辑类,封装实现登录功能的业务逻辑(控制类) |
UserDao | 抽象数据访问类接口,声明对user表的数据操作方法(实体类) |
UserDaoImpl | 具体数据访问类,实现对user表的数据操作方法(实体类) |
MainForm | 主窗口(边界类) |
各类中的方法说明如下表:
方法名 | 说明 |
---|---|
LoginForm类的LoginForm()方法 | LoginForm构造函数,初始化实例成员 |
LoginForm类的validate()方法 | 界面类的验证方法,通过调用业务逻辑类LoginBO的validate()方法实现对用户输入信息的验证 |
LoginBO类的validate()方法 | 业务逻辑类的验证方法,通过调用数据访问类的findUserByAccAndPwd()方法验证用户输入信息的合法性 |
LoginBO类的setUserDao()方法 | 在业务逻辑对象中注入数据访问对象 |
UserDao接口的findUserByAccAndPwd()方法 | 业务方法声明 |
UserDaoImpl接口的findUserByAccAndPwd()方法 | 业务方法实现,通过用户输入的账号和密码和数据库中的信息进行比对 |
UML类图设计如下:
java代码粗略实现:
public class LoginForm {
private LoginBO login;
public LoginForm() {
login = new LoginBO;
}
public boolean validate(String account, String password) {
return login.validate(account, password);
}
}
public class LoginBo {
@Autowire
private UserDao userDao;
public boolean validate(String account, String password) {
if (userDao.findUserByAccAndPwd(account, password)) {
return true;
}
return false;
}
}
public interface UserDao {
boolean findUserByAccAndPwd(String account, String password);
}
public class UserDaoImpl implements UserDao {
public boolean findUserByAccAndPwd(String account, String password) {
// select * from user where account=#{account} and password=#{password}
}
}
@Test
public void TestLogin {
// 接收用户输入的account和password
String account;
String password;
LoginForm loginForm = new LoginForm();
if (loginForm.validate(account, password)) {
// 进入主界面MainForm
} else {
// 提示登录失败
}
}