Java/Swift 单例模式的多种写法
2016-07-01 15:20
369 查看
设计模式的书本上一般是这样写:
public final class SingleTon {
private static SingleTon sInstance;
public static SingleTon getInstance() {
if (sInstance == null) {
sInstance = new SingleTon();
}
return sInstance;
}
}
仔细看这几行代码, 能发现什么问题吗? 脑洞大开一下。
1. 在外部类中可以new出SingleTon对象。
2. 多线程时怎么办? 可能生成多个SingleTon实例, 我们想到了锁。
public final class SingleTon {
private static SingleTon sInstance;
private SingleTon() {
//将构造函数声明成私有函数, 从而在类外部无法实例化该类
}
public synchronized static SingleTon getInstance() {
if (sInstance == null) {
sInstance = new SingleTon();
}
return sInstance;
}
}
添加synchronized关键字后实际上是SingleTon.class上锁, 但对函数上锁的颗粒度较大, 影响多线程并发的性能, 实际上我们只需要对new对象上锁, 读对象时不上锁。 更好的写法是
public final class SingleTon { private volatile static SingleTon sInstance; public static SingleTon getInstance() { if (sInstance != null) { return sInstance; } synchronized(SingleTon.class) { if (sInstance == null) { sInstance = new SingleTon(); } } return sInstance; } }
如果不使用锁, 能不能实现单例呢? 答案是可以的, 肯定要借助静态内部类了。 public final class SingleTon {
private SingleTon() {
}
private static class Inner {
static SingleTon sInstance = new SingleTon (); //私有静态类, 只会执行一次new
}
public static SingleTon getInstance() {
return Inner.sInstance;
}
}
这种写法看起来很高大上, 没用到synchroized关键字实现了锁, 保证一个进程只有一个实例。
Swift3.0单例模式的2个写法如下, 虽然没有同步关键字, 但苹果已经说了加上static关键字后多线程时也能保证是一个实例。
注意要声明init函数, 而且是private访问类型, 从而只能通过类的静态参数得到实例。
苹果的说明:In Swift, you can simply use a static type property, which is guaranteed to be lazily initialized only once, even when accessed across multiple threads simultaneouslyfinal class SingleTon {
//单例类的属性
var name: String
var age: Int
private init() {
name = ""
age = 0
print("SingleTon init is called")
}
static let sInstance = SingleTon()
}
final class SingleTon2 {
//单例类的属性
var name: String
var age: Int
private init() {
name = ""
age = 0
print("SingleTon init is called")
}
//使用闭包的GET语法, 类似于lazy参数, 在运行时赋初值
static var sInstance: SingleTon2 {
let instance = SingleTon2()
instance.name = "zhangsan"
instance.age = 20
return instance
}
}
在Swift语言中default是关键字, 如果想用default作为变量名, 可以转义。 PS: Swift的其它关键字也可以这样转义!!!
class SomeClass {
var param = 1
public static let `default` = SomeClass()
}
print(SomeClass.default.param)
public final class SingleTon {
private static SingleTon sInstance;
public static SingleTon getInstance() {
if (sInstance == null) {
sInstance = new SingleTon();
}
return sInstance;
}
}
仔细看这几行代码, 能发现什么问题吗? 脑洞大开一下。
1. 在外部类中可以new出SingleTon对象。
2. 多线程时怎么办? 可能生成多个SingleTon实例, 我们想到了锁。
public final class SingleTon {
private static SingleTon sInstance;
private SingleTon() {
//将构造函数声明成私有函数, 从而在类外部无法实例化该类
}
public synchronized static SingleTon getInstance() {
if (sInstance == null) {
sInstance = new SingleTon();
}
return sInstance;
}
}
添加synchronized关键字后实际上是SingleTon.class上锁, 但对函数上锁的颗粒度较大, 影响多线程并发的性能, 实际上我们只需要对new对象上锁, 读对象时不上锁。 更好的写法是
public final class SingleTon { private volatile static SingleTon sInstance; public static SingleTon getInstance() { if (sInstance != null) { return sInstance; } synchronized(SingleTon.class) { if (sInstance == null) { sInstance = new SingleTon(); } } return sInstance; } }
如果不使用锁, 能不能实现单例呢? 答案是可以的, 肯定要借助静态内部类了。 public final class SingleTon {
private SingleTon() {
}
private static class Inner {
static SingleTon sInstance = new SingleTon (); //私有静态类, 只会执行一次new
}
public static SingleTon getInstance() {
return Inner.sInstance;
}
}
这种写法看起来很高大上, 没用到synchroized关键字实现了锁, 保证一个进程只有一个实例。
Swift3.0单例模式的2个写法如下, 虽然没有同步关键字, 但苹果已经说了加上static关键字后多线程时也能保证是一个实例。
注意要声明init函数, 而且是private访问类型, 从而只能通过类的静态参数得到实例。
苹果的说明:In Swift, you can simply use a static type property, which is guaranteed to be lazily initialized only once, even when accessed across multiple threads simultaneouslyfinal class SingleTon {
//单例类的属性
var name: String
var age: Int
private init() {
name = ""
age = 0
print("SingleTon init is called")
}
static let sInstance = SingleTon()
}
final class SingleTon2 {
//单例类的属性
var name: String
var age: Int
private init() {
name = ""
age = 0
print("SingleTon init is called")
}
//使用闭包的GET语法, 类似于lazy参数, 在运行时赋初值
static var sInstance: SingleTon2 {
let instance = SingleTon2()
instance.name = "zhangsan"
instance.age = 20
return instance
}
}
在Swift语言中default是关键字, 如果想用default作为变量名, 可以转义。 PS: Swift的其它关键字也可以这样转义!!!
class SomeClass {
var param = 1
public static let `default` = SomeClass()
}
print(SomeClass.default.param)
相关文章推荐
- 设计模式之创建型模式 - 特别的变量问题
- C#单例模式(Singleton Pattern)实例教程
- php设计模式之单例、多例设计模式的应用分析
- javascript 单例/单体模式(Singleton)
- C++单例模式应用实例
- 浅谈Java编程中的单例设计模式
- Python单例模式实例分析
- Java单例模式实例简述
- 新手谈设计模式 - 单例模式
- JAVA语言泛型编程实现单例模式
- Swift之单例模式
- iOS设计模式之单例模式
- python logging 单例模式范例
- 单例模式
- 单例模式扩展
- 设计模式1-单例设计模式
- swift的函数,闭包,单例,KVC以及协议的基本写法
- iOS 单例模式全面解析
- 单例模式的反序列化总结
- C#窗口实现单例模式