定义:
Singleton模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在。
在很多操作中,比如建立目录 数据库连接都需要这样的单线程操作。
还有, singleton能够被状态化; 这样,多个单态类在一起就可以作为一个状态仓库一样向外提供服务,比如,你要论坛中的帖子计数器,每次浏览一次需要计数,单态类能否保持住这个计数,并且能synchronize的安全自动加1,如果你要把这个数字永久保存到数据库,你可以在不修改单态接口的情况下方便的做到。
另外方面,Singleton也能够被无状态化。提供工具性质的功能,
Singleton模式就为我们提供了这样实现的可能。使用Singleton的好处还在于可以节省内存,因为它限制了实例的个数,有利于Java垃圾回收(garbage collection)。
我们常常看到工厂模式中类装入器(class loader)中也用Singleton模式实现的,因为被装入的类实际也属于资源。
单例模式的两种代码体现形式
饱汉式
// 定义一个私有构造器,这样的话就不能通过new关键字在外部所实例化
private Singleton(){}
// 在jvm中创建该类的一个实例
private static Singleton singleton = new Singleton();
// 在外部通过调用此方法,访问该类的仅有的一个实例,达到该类资源共享的一个效果
public static Singleton getInstance(){
return singleton;
}
懒汉式
// 定义一个私有构造器,这样的话就不能通过new关键字在外部所实例化
private Singleton2(){}
// 在jvm中创建该类的一个实例
private static Singleton2 singleton = null;
// 在外部通过调用此方法,访问该类的仅有的一个实例,达到该类资源共享的一个效果
public static synchronized Singleton2 getInstance(){
if(null == singleton)
singleton = new Singleton2();
return singleton;
}
后期追加内容:
对一类问题行之有效的解决方案
单例设计模式
特点:解决一个类在内存中只存在一个对象。
案例:两个人操作同一个文件,将文件描述成类的话,那么两个人操作这个对象。用new的方法来操作的话,那么实际上是两个人操作的是不同的对象。这个时候,我们就需要让该类只能产生一个对象,供两个人来操作了,就需要用单例了。Tomcat的容器就是单例的。
饿汉式代码及内存原理图
懒汉式源码
建议单例使用饿汉式,代码更加简洁
单例模式的使用场景
这里举个简单的例子,网站访问量统计
在不考虑设计模式这一因素的情况下,我们最初是怎么统计网站统计量的呢?
这里需要写一个监听类、两个servlet来、一个JSP页面模拟网站访问统计的场景
public class InitListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
ServletContext context = sce.getServletContext();
context.setAttribute("count",0);
}
}
DemoServlet1.java
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = req.getServletContext();
int count = (int) context.getAttribute("count");
context.setAttribute("count",++count);
req.getRequestDispatcher("/index.jsp").forward(req,resp);
}
DemoServlet2.java
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = req.getServletContext();
int count = (int) context.getAttribute("count");
context.setAttribute("count",++count);
req.getRequestDispatcher("/index.jsp").forward(req,resp);
}
index.jsp
全局作用域统计网站访问量:${count}
那么不使用全局作用域,我们能否统计网站的访问量呢?
答案是肯定的,servlet中全局作用域之所以能够统计网站的访问量,缘由在于servlet容器是单例的,工程一旦启动完毕,application作用域是只有一个的,
关于网站中的所有请求用到的application都是同一个,所以我们可以那它用来统计访问量。参照这一原理,我们可以用单例模式来统计网站访问量。代码
如下:
这里可以不需要监听类
两个servlet代码如下,代码完全一致
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = req.getServletContext();
int count = (int) context.getAttribute("count");
Singleton singleton = Singleton.getInstance();
singleton.setCount(singleton.getCount()+1);
context.setAttribute("count",++count);
req.setAttribute("count2",singleton.getCount());
req.getRequestDispatcher("/index.jsp").forward(req,resp);
}
index.jsp
全局作用域统计网站访问量:${count}
单例模式统计网站访问量:${count2}
不管是移动端、还是电脑端,只要同一局域网,那么访问
http://localhost:8080/design/demo1
http://localhost:8080/design/demo2
都可以达到访问量+1的效果
谢谢大家,多多指教!!!
来源:CSDN
作者:冬.
链接:https://blog.csdn.net/qq_45174759/article/details/103484921