单例(Singleton)模式 从最初代码到一步步实现

public class AppConfig{
    private String parameterA;
    private String parameterB;
    public String getParameterA(){
        return parameterA;
    }
    public String getParameterB(){
        return oarameterB;
    }
    public AppConfig(){
        readConfig();
    }
    private void readConfig(){
        Properties p=new Properties();
        InputStream in=null;
        try{
            in=AppConfig.class.getResourceAsStream("AppConfig.properties");
            p.load(in);//获取资源文件的输入流,从输入流中读取属性列表
            this.parameterA=p.getProperty("paramA");
            this.parameterB=p.getProperty("paramB");
            }catch(IOException e){
                System.out.println("装载配置文件出错");
                e.printStackTrace();
            }finally{
                try{
                    in.close();
                }catch(IOException e){
                    e.printStrackTrace();
                }
            }
        }
    }
}
public class Client{
    public static void main(String[] args){
        AppConfig config=new AppConfig();
        String paramA=config.getParameterA();
        String paramB=config.getParameterB();
        System.out.println("paramA="+paramA+",paramB="+paramB);
    }
}

存在的问题:
● 如果在系统运行中,多处都需要使用配置文件的内容,也就是说有很多地方都需要创建AppConfig对象的实例
● 即在系统运行时,系统会存在很多个AppConfig的实例对象
● 如果配置文件较大,将是对资源的很大的浪费

解决方案——单例模式
在这里插入图片描述
● 单例(Singleton)模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
● Singleton模式解决问题十分常见:创建一个唯一的变量(对象)
● Singleton模式是设计模式中最为简单、最为常见、最容易实现,也是最应该熟悉和掌握的模式。
● Singleton模式只包含一个角色,就是Singleton。
● Singleton拥有一个私有构造函数,确保用户无法通过new直接实例它。
● 该模式中包含一个静态私有成员变量instance与静态公有方法GetInstance。GetInstance方法负责检验并实例化自己,然后存储在静态成员变量中,以确保只有一个实例被创建。

单例类

class Singleton{
    private static Singleton instance;
    private Singleton(){
        //构造方法为private,外界就不能利用new创建此类型的实例
    }
    public static Singleton GetInstance(){
        if(instance == null){
            //如果实例不存在则new一个新实例,否则返回已有的实例
            instance = new Singleton();
        }
        return instance;
    }
    public static void main(String[] args){
        //Singleton s0 = new Singleton();
        //错误,外界不能通过new来创建此类型实例
        Singleton s1 = Singleton.GetInstance();
        Singleton s2 = Singleton.GetInstance();
        if(s1 == s2)//判断2次实例化后对象的结果是实例相同
            System.out.print("两个对象是相同的实例");
        else
            System.out.print("两个对象是不同的实例");
    }
}

● 单例模式的特点:
◇单例类只能有一个实例
◇单例类必须自己创建自己的唯一实例
◇单例类必须给所有其它对象提供这一实例
● 单例模式的优点:
◇可以办证唯一的实例。
◇保证对唯一实例的受控访问。

多线程时的单例

public class Singleton{
    private static Singleton instance;
    private static final Object syncRoot = object();
    //程序运行时创建一个静态只读的进程辅助对象
    public static Singleton getInstance(){
        synchronized(syncRoot)
        //在同一个时刻加了锁的部分程序只有一个线程可以进入
        {
            if(instance == null)
            { instance = new Singleton();}
        }
        System.out.println("singleton创建");
        return instance;
    }
    public static void main(String[] args){
        Singleton singleton1 = Singleton.getInstance();
        Singleton singleton2 = Singleton.getInstance();
        if(singleton1 == singleton2){
        System.out.print("该对象的字符串表示形式:");
        System.out.print("singleton1:"+singleton1.toString());
        System.out.print("singleton2:"+singleton2.toString());
        }//在同一个时刻加了锁的部分程序只有一个线程可以进入
    }
}

问题:
● 上面的代码在每次调用getInstance方法时都需要同步,降低了性能
● 解决:双重锁定
不用让线程每次都加锁,而只是在实例未被创建的时候加锁,同时也保证多线程的安全。

public class SingletonDCL{
    private volatile static SingletonDCL singleton;
    private SingletonDCL(){}
    public static SingletonDCL getInstance(){
    //此方法是获得本例实例的唯一全局访问点
	    if(singleton == null){
	        //给类加锁,类的所有对象用同一把锁
	        synchronized(SingletonDCL.class){
	            if(singleton == null){
	                singleton = new SingletonDCL();
	            }
	            System.out.println("singleton创建");
	            return singleton;
	        }
	    }
    }
    public static void main(String[] args){
        SingletonDCL singleton1=SingletonDCL.getInstance();
        SingletonDCL singleton2=SingletonDCL.getInstance();
        System.out.println("singleton1 == singleton2?"+(singleton1==singleton2));
        System.out.println("该对象的字符串表示形式:");
        System.out.println("singleton1:"+singleton1.toString());
        System.out.println("singleton2:"+singleton2.toString());
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值