网上收集整理,仅做笔记参考学习
1.单例模式
确保一个类只有一个实例,并提供该实例的全局访问点。
优点:
1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。
2、避免对资源的多重占用(比如写文件操作)。
懒汉式-线程不安全
懒汉式,顾名思义就是实例在用到的时候才去创建
1、懒汉式,线程不安全
是否 Lazy 初始化:是
是否多线程安全:否
实现难度:易
描述:这种实现最大的问题就是不支持多线程。因为没有加锁 synchronized,所以严格意义上它并不算单例模式。
这种方式 lazy loading 很明显,不要求线程安全,在多线程不能正常工作。
public class Singleton{
private static Singleton intance;
//构造器
private Singleton(){
}
public static Singleton getInstance(){
if(intance == null){
intance = new Singleton();
}
return intance;
}
}
懒汉式-线程安全
区别就是是否getInstance()
是否由synchronized
关键字
是否多线程安全:是
缺点:必须加锁 synchronized
才能保证单例,但加锁会影响效率。
getInstance() 的性能对应用程序不是很关键(该方法使用不太频繁)
public class Singleton{
private static Singleton intance;
//构造器
private Singleton(){
}
public static synchronized Singleton getInstance(){
if(intance == null){
intance = new Singleton();
}
return intance;
}
}
饿汉式
是否 Lazy 初始化:否
是否多线程安全:是
描述:这种方式比较常用,但容易产生垃圾对象。
优点:没有加锁,执行效率会提高。
缺点:类加载时就初始化,浪费内存。
instance 在类装载时就实例化,虽然导致类装载的原因有很多种,在单例模式中大多数都是调用 getInstance 方法, 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化 instance 显然没有达到 lazy loading 的效果。
public class Singleton{
private static Singleton instance = new Singleton();
//构造器
private Singleton(){}
public static Singleton getInstance(){
return instance;
}
}
2.代理模式
在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。
缺点:
1、由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。
2、实现代理模式需要额外的工作,有些代理模式的实现非常复杂。
1.创建一个Image类
public interface Image {
void display();
}
2.1创建Image类的实现类ImpImage
public class ImpImage implements Image {
private String fileName;
public ImpImage(String fileName) {
this.fileName = fileName;
loadImage(fileName);
}
@Override
public void display() {
System.out.println("displaying " + fileName);
}
private void loadImage(String fileName){
System.out.println("loading " + fileName);
}
}
2.2创建Image类的代理实现类ImpProxyImage
public class ImpProxyImage implements Image {
private String fileName;
private ImpImage impImage;
public ImpProxyImage(String fileName) {
this.fileName = fileName;
}
@Override
public void display() {
if(impImage == null){
impImage = new ImpImage(fileName);
}
impImage.display();
}
}
3.当被请求时,使用ImpProxyImage来获取ImpImage
类的对象
public class ProxyPatternDemo {
public static void main(String[] args) {
Image image = new ImpProxyImage("image_10");
image.display();//第一次impImage为null,所以需要加载
image.display();//第二次不为空,所以直接调用方法
}
}
运行结果
第一次impImage为null,所以需要加载后,在调用方法
第二次不为空,所以直接调用方法
loading image_10
displaying image_10
displaying image_10