单例模式与多例模式的案例设计分析
Singleton and Multition Pattern单例模式与多例模式
目录
一、细说单例模式
1、单例模式的定义与特点
2、模式的结构与实现
单例模式场景:
上代码:
二、细说多例模式
单例模式场景:
上代码:
一、细说单例模式
1、单例模式的定义与特点
单例(Singleton)模式的定义:指一个类只有一个实例,且该类能自行创建这个实例的一种模式。例如,Windows 中只能打开一个任务管理器,这样可以避免因打开多个任务管理器窗口而造成内存资源的浪费,或出现各个窗口显示内容的不一致等错误。
在计算机系统中,还有 Windows 的回收站、操作系统中的文件系统、多线程中的线程池、显卡的驱动程序对象、打印机的后台处理服务、应用程序的日志对象、数据库的连接池、网站的计数器、Web 应用的配置对象、应用程序中的对话框、系统中的缓存等常常被设计成单例。
单例模式有 3 个特点:
- 单例类只有一个实例对象;
- 该单例对象必须由单例类自行创建;
- 单例类对外提供一个访问该单例的全局访问点;
2、单例模式的结构与实现
单例模式是设计模式中最简单的模式之一。通常,普通类的构造函数是公有的,外部类可以通过“new 构造函数()”来生成多个实例。但是,如果将类的构造函数设为私有的,外部类就无法调用该构造函数,也就无法生成多个实例。这时该类自身必须定义一个静态私有实例,并向外提供一个静态的公有函数用于创建或获取该静态私有实例。
下面来分析其基本结构和实现方法。
单例模式场景:
世界上只有一个月亮,月亮的直径是3476.28km,无论在中国还是在美国,我们所看到的都是同一个月亮。使用单例模式实现无论我们在哪所看到的月亮是同一个月亮(饿汉单例模式、懒汉单例模式),绘制类图并编程实现。
场景设计与实现
结构如图所示:
上代码
代码一
/*单例类*/
package com.rjs.singleton;
//懒汉模式
public class Mood {
private static Mood mood=null;
private static double distance=3476.28;
private Mood() {
System.out.println("产生一个月亮");
}
public static synchronized Mood getMood() {
//在getMood方法上加上同步
if(mood==null) {
mood=new Mood();
}else {
System.out.println("已经产生了一个月亮,不能产生新的月亮!");
}
return mood;
}
public void getDistance() {
System.out.println("我是月亮,我的直径是:"+distance+"km.");
}
}
/*访问类*/
package com.rjs.singleton;
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
Mood americaMood=Mood.getMood();
System.out.println("====我来自美国=====");
americaMood.getDistance();
System.out.println("====我来中国=====");
Mood chinaMood=Mood.getMood();
chinaMood.getDistance();
}
}
代码二:
二、细说多例模式
结合单例模式来说多例模式,单例模式相对来说比较容易理解一点,也就是在整个应用程序运行过程中,这个类的实例永远都是一个,好比如历朝历代,皇帝在大多数情况下都是只有一个,但是往往在程序运行过程中,我可能为了达到复用的效果,需要在一个池子中去选择对应的实例进行使用,这个时候多例模式也就应运而生了。
所谓多例模式其实也就是类的对象实例是有多个,但是这个多个也要区别于无限个,当然,如果一个类的对象可以有无限个的话,那能不能叫多例呢??这个可能就需要区别多例模式的特点了
所谓多例(Multiton Pattern)实际上就是单例模式的自然推广,属于对象
创建类型的模式,多例模式其实就是限制了对象的数量,并且有可能对对象进行重复使用
特点:
1:多例可以有多个实例
2: 多例类必须能够自我创建并管理自己的实例,并且向外界提供自己的实例
多例模式场景:
在java学习过程中,有一个池子的概念一直存在,好比作线程池,数据库连接池,这个池子是用来对线程,或者数据库连接对象进行管理的,第一,限制了池子中的对象数量,第二就是能够在使用过程中达到复用的效果,线程中的线程在执行完毕后,不会被直接回收掉,而会切换成等待状态,等待下一个任务提交,执行。数据库连接池也是如此,数据库操作在连接的时候,如果对数据库操作完毕后,会把资源释放,然后等待下一个数据库操作进行连接。这种设计其实是将对象的应用最大化了,避免了每次连接的时候都需要去创建一个对象。造成对象冗余或者内存升高。
场景的设计与实现
结构如图所示:
上代码:
/*单例类*/
package com.rjs.singletonDataPool;
import java.util.ArrayList;
import java.util.Random;
public class SQLConnectionPools {
private static int maxNumOfConnection= 3;
private static ArrayList<String> connectionInfoList = new ArrayList<>(maxNumOfConnection);
private static ArrayList<SQLConnectionPools> connArrayList = new ArrayList<>(maxNumOfConnection);
private static int currNumOfConnection =0;
private SQLConnectionPools() {
// TODO Auto-generated constructor stub
}
private SQLConnectionPools(String info) {
connectionInfoList.add(info);
}
static{
for (int i = 0; i < maxNumOfConnection; i++) {
connArrayList.add(new SQLConnectionPools(i+"号连接"));
}
}
public static SQLConnectionPools getInstance() {
Random random = new Random();
currNumOfConnection = random.nextInt(maxNumOfConnection);
return connArrayList.get(currNumOfConnection);
}
public void connectionInfo() {
System.out.println(connectionInfoList.get(currNumOfConnection));
}
}
/*访问类*/
package com.rjs.singletonDataPool;
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int userNum=10;
for(int i=0;i<userNum;i++){
//用户获取到的连接时随机的
SQLConnectionPools conn= SQLConnectionPools.getInstance();
System.out.print("第"+i+"个用户获得的连接是:");
conn.connectionInfo();
}
}
}
参考: