单例

和其它语言的单例产不多,可以说是最简单的一种设计模式了。但是有几个点需要注意下,单例就是一个类只有一个实例。

所以我们要想办法阻止该类产生别的实例,一般语言中都会将构造函数写为private。但是OC中的函数并没有限定符,所以我们需要用一些小技巧来屏蔽这一点。

应用场景

类只能有一个实例,而且必须从一个为人熟知的访问点对其进行访问,比如工厂方法。

这个唯一的实例只能通过类的子类化进行扩展,而且扩展的对象不会破坏客户端代码。

注意

1.OC中单例的实例变量要定义在.m文件

2.OC中单例需要重载allocWithZone:和copyWithZone:方法来防止创建别的实例。

3.单例创建要注意线程安全,不然就可能出现多个实例。

注意问题将会在Demo中讲解

Demo

首先先来看一个最常规,的不严谨的单例实现:

@implementation Singleton

static Singleton *sharedInstance;

-(Singleton *)sharedInstance
{
if(sharedInstance)
{
sharedInstance = [Singleton new];
}
return sharedInstance;
} @end

这看似好像是可以得到单例对象了,但是这可以说是单例的一种变形。绝不能说这就是单例,因为我们可以轻松地通过其他方式来创建对象。

所以我们还要我修改allocWithZone:和copyWithZone:方法(alloc 和 copy 方法实际上就是调用这两个方法)

-(id)copyWithZone:(NSZone *)zone
{
return [[self class] sharedInstance];
} +(id)allocWithZone:(struct _NSZone *)zone
{
return [self sharedInstance];
}

可是这就出现另一个问题,在sharedInstance方法里面我们实际调用过allocWithZone:(new 调用 alloc),但是它的alloc被我们重写了,这就会出现错误。所以我们需要修改sharedInstance方法

+(Singleton *)sharedInstance
{
if(sharedInstance)
{
sharedInstance = [[super allocWithZone:NULL] init];
}
return sharedInstance;
}

这样就可以顺利的返回单例了,而且无法通过其它方式产生实例对象。

看似完美了实际还会有问题出现,因为现在是非线程安全的,可能存在同一时间创建多个实例的情况,所以修改如下

+(instancetype)sharedInstance
{
static dispatch_once_t once;
dispatch_once(&once, ^{
sharedInstance = [[super allocWithZone:NULL] init];
});
return sharedInstance;
}

客户端代码如下:

        Singleton *singleton = [Singleton sharedInstance];
Singleton *singleton2 = [[Singleton alloc] init];
Singleton *singleton3 = [singleton copy]; [singleton print];
[singleton2 print];
[singleton3 print];

输出结果:

-- ::32.797 Singleton[:] 0x7fff5fbff7a8
-- ::32.798 Singleton[:] 0x7fff5fbff7a8
-- ::32.798 Singleton[:] 0x7fff5fbff7a8

可以看到内存都指向了同一地址。

Objective-C设计模式——单例Singleton(对象创建)的更多相关文章

  1. Android与设计模式——单例(Singleton)模式

    概念: java中单例模式是一种常见的设计模式.单例模式分三种:懒汉式单例.饿汉式单例.登记式单例三种. 单例模式有一下特点: 1.单例类仅仅能有一个实例. 2.单例类必须自己自己创建自己的唯一实例. ...

  2. java设计模式-单例(singleton)

    单例模式,是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例的特殊类.通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例.即一个类只有一个对象实例 如何保证对象唯一性呢? 思想: ...

  3. go设计模式--单例singleton

    创建型第一个,使用TDD作的. singleton.go package singleton type Singleton interface { AddOne() int } type single ...

  4. OpenJDK源码研究笔记(十三):Javac编译过程中的上下文容器(Context)、单例(Singleton)和延迟创建(LazyCreation)3种模式

    在阅读Javac源码的过程中,发现一个上下文对象Context. 这个对象用来确保一次编译过程中的用到的类都只有一个实例,即实现我们经常提到的"单例模式". 今天,特意对这个上下文 ...

  5. 跨应用程序域(AppDomain)的单例(Singleton)实现

    转载自: 跨应用程序域(AppDomain)的单例(Singleton)实现 - CorePlex代码库 - CorePlex官方网站,Visual Studio插件,代码大全,代码仓库,代码整理,分 ...

  6. Java设计模式—单例设计模式(Singleton Pattern)全然解析

    转载请注明出处:http://blog.csdn.net/dmk877/article/details/50311791 相信大家都知道设计模式,听的最多的也应该是单例设计模式,这种模式也是在开发中用 ...

  7. Java设计模式之 — 单例(Singleton)

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/8860649 写软件的时候经常需要用到打印日志功能,可以帮助你调试和定位问题,项目上 ...

  8. Java设计模式透析之 —— 单例(Singleton)

    写软件的时候经常需要用到打印日志功能,可以帮助你调试和定位问题,项目上线后还可以帮助你分析数据.但是Java原生带有的System.out.println()方法却很少在真正的项目开发中使用,甚至像f ...

  9. java设计模式——单例(Singleton)模式

    在某些场景,你需要找到一个承担职责的对象,并且这个对象是他所属类的唯一实例.此时可以使用单例模式. 单例模式的意图是为了确保一个类有且仅有一个实例,并为他提供一个全局的访问点.创建一个担当独一无二角色 ...

随机推荐

  1. spring history &design Philosophy

    Spring简介 Spring是一个开源框架,它由Rod Johnson创建.它是为了解决企业应用开发的复杂性而创建的.Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情.然而, ...

  2. Hive之执行计划分析(explain)

    Hive是通过把sql转换成对应mapreduce程序,然后提交到Hadoop上执行,查看具体的执行计划可以通过执行explain sql知晓 一条sql会被转化成由多个阶段组成的步骤,每个步骤有执行 ...

  3. mysql: reinit the password

    You can reinit the password : 1.stop mysql /etc/init.d/mysql stop 2.start mysql safe : mysqld_safe - ...

  4. Spring PropertyPlaceholderConfigure 载入配置文件

    在開始这篇博客的主题之前,我们先来了解一下Spring配置文件以及包括的相关内容. watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2 ...

  5. Linux学习系列之lvs+keepalived

    LVS简介 LVS介绍 LVS是Linux Virtual Server的缩写,意即Linux虚拟服务器,是一个虚拟的服务器集群系统,属于4层负载均衡 ipvs和ipvsadm的关系 我们使用配置LV ...

  6. Android.mk文件解析

     一.一个简单的Android.mk文件例如以下: LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := nativ ...

  7. matlab Newton method

    % Matlab script to illustrate Newton's method % to solve a nonlinear equation % this particular scri ...

  8. Ubuntu18.04系统中vi键盘输入字符不匹配

    起因 今天重装了我的雷神笔记本的ubuntu18.04,不要问我为什么,我就是想复习下重装系统而已.好吧,我承认我改错文件启动不起来了. 于是我要重装jdk.maven and so on,但是当我用 ...

  9. HQL 查询数据 (获取页面输入的查询条件字段)

    /* * 查询提取位置表所有数据 * */ public String ListEtlExtractPositionOfAll(){ // 接受数据库中传送的code int code = Integ ...

  10. 【Codevs 1376】帕秋莉•诺蕾姬

    http://codevs.cn/problem/1376/ 枚举修改哪两位,将sum减去之前位置的数+交换之后  %m==0即可 预处理26的次方+O(n^2) // <1376.cpp> ...