前几天校园招聘会,投简历时就直接给我来了一份笔试题。我一看,卧槽,全都是考很基本很基本的题,可以说基本到恶心,然而对于我这个实习了半年,可以独自把一个项目完成的程序猿来说,很可惜这些基本题却把我放倒了,真是讽刺啊。就感觉一个全栈工程师被问如何输出一个helloworld被吓得跪地直喊OMG一样,哈哈,开个玩笑。没办法,面向学生招聘,企业都爱玩这一套,对于我这个有实战经验的人来说,尽管这些基本的东西感觉在实际项目还真不怎么用得上,但还是得去沉淀一下啊。
笔试题的组成基本少不了数据结构和设计模式,既然你把我放倒了,那么我就从设计模式开始补回来吧,坚持一天一种模式学习吧。
首先是设计模式里最简单的一种模式,单例模式。顾名思义,就是一个类,在使用的时候确保只有一个实例被初始化。
第一步,创建一个单例类:
SingleTon.java
public class SingleTon { private static SingleTon instance; private int count; //构造方法为私有,无法直接new()获得实例 private SingleTon(){ count=0; } public static SingleTon getInstance(){ if(instance==null){ instance=new SingleTon(); } return instance; } public void print(){ System.out.println(count); } public void add(){ System.out.println("变量加1"); count++; } }
PatternTest.java
public class PatternTest { public static void main(String[] args) { // TODO Auto-generated method stub SingleTon singleTon1=SingleTon.getInstance(); singleTon1.print(); singleTon1.add(); SingleTon singleTon2=SingleTon.getInstance(); singleTon2.print(); } }
运行结果:
果然很简单吧,两次获取实例都是同一个实例,所以加一操作add()也只是在同一个对象上的成员变量加一。
不过,对于单例模式,若是比较起其性能,如内存,线程安全等,则有几种不同的实现方式。
1. 节省内存(懒汉模式),非线程安全式:
public class SingleTon { private static SingleTon instance; //构造方法为私有,无法直接new()获得实例 private SingleTon(){} public static SingleTon getInstance(){ if(instance==null){ instance=new SingleTon(); } return instance; } }实际上就和上面一开始的代码一样,只有使用时才实例化,但没有考虑到线程安全。
2. 节省内存, 线程安全,效率慢式:
public class SingleTon { private static SingleTon instance; //构造方法为私有,无法直接new()获得实例 private SingleTon(){} public static synchronized SingleTon getInstance(){ if(instance==null){ instance=new SingleTon(); } return instance; } }就是在getInstance()方法里加个同步锁而已,虽然可以达到线程安全,但效率慢。
3. 耗内存,线程安全,效率快式:
public class SingleTon { private static SingleTon instance=new SingleTon(); //构造方法为私有,无法直接new()获得实例 private SingleTon(){} public static SingleTon getInstance(){ return instance; } }就直接在加载类的时候就初始化了,这样会耗内存,但不使用synchronize锁,这样就可以不用加同步锁也可以达到线程安全的效果。
实际上还有其他的方式,但一般都是使用第三种方式创建单例多。