单例模式

单例模式介绍
单例模式是应用最广泛的模式之一,也可能是很多刚入门的工程师唯一会使用的设计模式。在应用这个模式时,单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个全局对象,这样有利于我们协调系统的整体行为。
如:在一个应用中,应该只有一个ImageLoader实例,这个ImageLoader中又含有线程池、缓存系统、网络请求等,很消耗资源,因此,没有理由让他构造多个实例。这种不能自由构造对象的情况,就是单例模式的使用场景。
单例模式的简单示例
单例模式是设计模式中比较简单的,只有一个单例类,没有其他的层次结构与抽象。该模式要确保该类只能生成一个对象,通常是该类需要消耗较多的资源或者没有多个实例的情况。例如,一个公司只有一个CEO、一个应用只有一个Application对象等。下面以公司里的CEO为例来简单演示一下,一个公司可以有几个VP、无数个员工,但CEO只有一个。

饿汉单例模式

package com.example.xll.singleton;

/**
 * 功能:普通员工类
 * 作者:xll
 * 日期:2016/11/17
 * 邮箱:liangliang.xu1110@gmail.com
 */

public class Staff {
    public void work(){
        //干活
    }
}
package com.example.xll.singleton;

/**
 * 功能:副总裁
 * 作者:xll
 * 日期:2016/11/17
 * 邮箱:liangliang.xu1110@gmail.com
 */

public class VP extends Staff {
    @Override
    public void work() {
        //管理下面的经理
    }
}
package com.example.xll.singleton;

/**
 * 功能:CEO,饿汉单例模式
 * 作者:xll
 * 日期:2016/11/17
 * 邮箱:liangliang.xu1110@gmail.com
 */

public class CEO extends Staff {
    private static final CEO mCeo = new CEO();

    //构造函数私有
    private CEO(){

    }

    //公有的静态函数,对外暴露获取单例对象的接口
    public  static CEO getmCeo(){
        return mCeo;
    }

    @Override
    public void work() {
        //管理VP
    }
}
package com.example.xll.singleton;

import android.util.Log;

import java.util.ArrayList;
import java.util.List;

/**
 * 功能:公司类
 * 作者:xll
 * 日期:2016/11/17
 * 邮箱:liangliang.xu1110@gmail.com
 */

public class Company {
    private List<Staff> mStaffList = new ArrayList<>();

    public void addStaff(Staff person){
        mStaffList.add(person);
    }

    public void showAllStaffs(){
        for (Staff person : mStaffList) {
            Log.i("员工:", person.toString());
        }
    }
}
package com.example.xll.singleton;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

/**
 * 功能:测试
 * 作者:xll
 * 日期:2016/11/17
 * 邮箱:liangliang.xu1110@gmail.com
 */
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Company cp  = new Company();
        //CEO对象只能通过getCeo函数获取
        Staff ceo1 = CEO.getmCeo();
        Staff ceo2 = CEO.getmCeo();
        cp.addStaff(ceo1);
        cp.addStaff(ceo2);

        //通过new创建VP对象
        Staff vp1 = new VP();
        Staff vp2 = new VP();

        //通过new创建Staff对象
        Staff staff1  = new Staff();
        Staff staff2  = new Staff();
        Staff staff3  = new Staff();

        cp.addStaff(vp1);
        cp.addStaff(vp2);
        cp.addStaff(staff1);
        cp.addStaff(staff2);
        cp.addStaff(staff3);

        cp.showAllStaffs();
    }
}

输出结果如下:
这里写图片描述

从上述代码中可以看到,CEO类不能通过new的形式构造对象,只能通过CEO.getmCeo()函数来获取,而CEO对象是静态对象,并且在声明的时候就已经初始化,这就保证了CEO对象的唯一性。从输出结果中发现,CEO两次输出的CEO对象都是一样的,而VP、Staff等类型的对象都是不同。这个实现的核心在于将CEO类的构造方法私有化,使得外部程序不能通过构造函数来构造CEO对象,而CEO对象通过一个静态方法返回一个静态对象。

懒汉单例模式
懒汉模式是声明一个静态对象,并且在用户第一次调用getInstance时进行初始化,而上述饿汉模式(CEO类)实在声明静态对象时就已经初始化。

package com.example.xll.singleton;

/**
 * 功能:懒汉模式
 * 作者:xll
 * 日期:2016/11/17
 * 邮箱:liangliang.xu1110@gmail.com
 */

public class Singleton {
    private static Singleton instance;

    private Singleton(){

    }

    public static synchronized Singleton getInstance(){
        if(instance==null){
            instance = new Singleton();
        }
        return instance;
    }
}

大家可能已经发现了,getInstance()方法中添加了synchronized关键字,也就是getInstance()的一个同步方法,这是在多线程情况下保证单例对象唯一性的手段。细想一下,大家可能会发现一个问题,即使instance已经被初始化(第一次调用时会被初始化),每次调用getInstance方法都会进行同步,这样会消耗不必要的资源,这也是懒汉式单例模式存在的最大问题。
最后总结一下,懒汉单例模式的优点是单例只有在使用时才会被实例化,在一定程度上节约了资源;缺点是第一次加载时需要及时进行实例化,反应稍慢,最大的问题是每次调用getInstance都进行同步,造成不必要的同步开销。这种模式一般不建议使用。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值