单例模式
1. 单例模式介绍
单例模式是使用最广泛的一模式之一也可能是很多初级工程师唯一会使用的设计模式。在应用这个模式时,单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个全局对象,这样有助于我们协调系统整体的行为。如在一个应用中,应该只有一个ImageLoader实例,这个Imageloader中又含有线程池、缓存系统、网络请求等,很消耗资,因此,没有理由让它构造多个实例。这种不能自由构造对象的情况,就是单例模式的使用场景。
2.单例的定义
确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
3.单例模式的使用场景
确保某个类有且仅有一个对象的场景,避免产生对个对象,消耗过多的资源,或者某种类型的对象只应该有且只有一个。例如,创建一个对象而要消耗的资源过多,如要访问IO和数据库等资源,这是就需要考虑单例模式。
4.单例模式的UML类图和角色划分
- 单例模式uml类图
- 单例模式角色划分
- Client:高层客户端
- Singleton:单例类
- 实现单例模式的关键点
- 构造函数不对外开发,一般为private;
- 通过一个静态方法或者枚举返回单例类的对象;
- 确保单例类的对象有且只有一个,尤其是在多线程环境下;
- 确保单例类对象在反序列化是不会重新构建对象。
5.单例模式的简单示例
单例模式时设计模式中比较简单的,只有一个但单例类,没有其它的层次结构与抽象,该模式需要确保该类只能生产一个对象,例如,一个公司只有一个CEO、一个应用只有一个Application对象等,下面以公司里面的CEO为例来简单演示一下,一个公司可以有几个vip、无数个员工,但是CEO只有一个,请看下面示例。
- 示例实现代码
Staff.java
/**
* Created by zhangqing on 2018/3/14.
* 普通员工
*/
public class Staff {
public void work() {
// /干活
}
}
VP.java
/**
* Created by zhangqing on 2018/3/14.
* 副总裁
*/
public class VP extends Staff{
@Override
public void work() {
//管理下面的经理
}
}
CEO.java
/**
* Created by zhangqing on 2018/3/14.
* CEO,饿汉单例模式
*/
public class CEO extends Staff {
private static final CEO mCeo = new CEO();
//构造函数私有
private CEO() {
}
//公有的静态函数,对外暴露获取单例对象的接口
public static CEO getmCeo() {
return mCeo;
}
@Override
public void work() {
//管理VP
}
}
Company.java
/**
* Created by zhangqing on 2018/3/14.
* 公司类
*/
public class Company {
private List<Staff> allStaffs = new ArrayList<>();
public void addStaff(Staff staff) {
allStaffs.add(staff);
}
public void showAllStaffs() {
for (Staff staff : allStaffs) {
System.out.println("Obj:" + staff.toString());
}
}
}
Test .java
public class Test {
public static void main(String[] agrs) {
Company company = new Company();
//CEO对象只能通过getCeo函数获取
Staff ceo1 = CEO.getmCeo();
Staff ceo2 = CEO.getmCeo();
company.addStaff(ceo1);
company.addStaff(ceo2);
//通过new 创建vp对象
Staff vp1 = new VP();
Staff vp2 = new VP();
company.addStaff(vp1);
company.addStaff(vp2);
//通过new创建staff对象
Staff staff1 = new Staff();
Staff staff2 = new Staff();
Staff staff3 = new Staff();
company.addStaff(staff1);
company.addStaff(staff2);
company.addStaff(staff3);
company.showAllStaffs();
}
}
测试输出结果: