设计模式个人总结-单例模式

125 阅读3分钟

单例模式

介绍

单例模式可能是所有程序员接触的最早的设计模式,即程序中只存在一个实例。一般在静态语言中会使用static关键字来声明要使用的单例,js中一般使用原型链完成单例的效果。

iOS

+ (instancetype)manager {
    static SpeBaseHTTPRequestManager *manager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [[self alloc] init];
    });
    return manager;
}

android

public abstract class SpeSqliteAbstractDBService extends SQLiteOpenHelper {
    public static final     String TAG     = "SpeSqliteDBService";
    public static           SpeSqliteAbstractDBService instance  = null;
    public Context          context = null;
    public SQLiteDatabase db = null;
    public Class            roomClass;
    /**
     * 提供回调给调用者,通知其数据库状态
     */
    public SpeSqliteBaseInterface listener;

    /**
     * 利用SQLiteOpenHelper的特性发起升级流程
     * @param context context
     */
    public SpeSqliteAbstractDBService(Context context) {
        super(context, SpeSqliteUpdateManager.getInstance().init(context).currentAppDBSetting().dbName,
                null, SpeSqliteUpdateManager.getInstance().init(context).currentAppDBSetting().dbVersion);
    }

}

js

MQTTManager.prototype.initMQTTSDK = function(appID, admin,onReceivedMsgCallBack,onSDKStateChanedCallback) {
    var deviceId = new DeviceUUID().get();
    this.httpposter = new MQTTPoster(appID, deviceId, admin);
    this.receivedMsgCallBack = onReceivedMsgCallBack;
    this.sdkStateChanedCallback = onSDKStateChanedCallback;
    this.getLoginParams();
    return this
}

使用时机

存在作用域为全局的工具类或服务类(这个全局可以拆分成子组件中的全局)。

注意点

1、单例可以方便的解决全局数据共享问题或服务共享问题,但是因为是常驻内存中,所以单例的创建要有控制。

2、单例创建时需要注意初始化的时机,防止众多单例一起初始化导致服务或应用卡顿。

3、注意某些动态库和静态库混合编译时的多单例问题。

iOS下单例多次初始化问题

1.由于某app是模块化开发,主工程会依赖多个业务模块(动态库)和BaselibModule(动态库)。

2.各个业务模块也会依赖BaselibModule

3.当动态库依赖动态库时,上一级动态库同样需要确认位置,此时会按这个动态库的依赖顺序去查找谁可以给它确定这个位置。

4.静态库链接时,方法的调用位置也是按链接顺序确认,静态库能找到则取app内的地址偏移。

5.根据编译原理分析: 每个可执行模块(包括可执行文件和动态链接库)都有自己的数据段用来存放自己的全局变量,即每个可执行模块下的static全局变量都有自己的内存区域,所以导致单例初始化两次。蓝知app可执行模块包括主工程和各个子动态库。

6.优化方案:由于之前所有模块都会依赖BaselibModule,所以在主工程下使用单例时要加一层封装类,此封装类创建在BaselibModule中,这样即可保证单例对象来自同一可执行模块。

总结

1.单例使用时机还是比较好识别的,一般情况下会融合其它设计模式一起发挥作用,其实还是单一职责的一个延伸场景。

参与贡献

  1. hfqf123@126.com