java通关整理-设计模式(单例模式、代理模式)

网上收集整理,仅做笔记参考学习

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

猜你喜欢

转载自blog.csdn.net/weixin_45773603/article/details/108070822
今日推荐