为了账号安全,请及时绑定邮箱和手机立即绑定

《设计模式——单例模式【安卓巴士博文大赛】》

标签:
Android

  作为开发者的我们,想必设计模式对大家来说并不陌生,设计模式共有23种,分别是:工厂方法(FactoryMethod)、抽象工厂(AbstractFactory) 、建造者模式(Builder)、单态模式(Singleton)、 原型模式(Prototype)、 适配器模式(Adapter)、桥接模式(Bridge) 、组合模式(Composite) 、装饰模式(Decorator)、外观模式(Facade)、 享元模式(Flyweight)、代理模式(Proxy)、责任链模式(Chain of Responsibility)、 命令模式(Command)、 解释器模式(Interpreter) 、迭代器模式(Iterator)、中介者模式(Mediator)、备忘录模式(Memento)、观察者模式(Observer)、状态模式(State)、策略模式(Strategy) 、模板方法(TemplateMethod)、访问者模式(Visitor)。这23种设计模式又分为三类,分别是:创建型模式、结构型模式和行为型模式。创建型模式分别包含的是工厂方法(FactoryMethod)、抽象工厂(AbstractFactory) 、建造者模式(Builder)、单态模式(Singleton)、 原型模式(Prototype)。结构型模式分别包含的是: 适配器模式(Adapter)、桥接模式(Bridge) 、组合模式(Composite) 、装饰模式(Decorator)、外观模式(Facade)、 享元模式(Flyweight)、代理模式(Proxy)。行为型模式分别包含的是:责任链模式(Chain of Responsibility)、 命令模式(Command)、 解释器模式(Interpreter) 、迭代器模式(Iterator)、中介者模式(Mediator)、备忘录模式(Memento)、观察者模式(Observer)、状态模式(State)、策略模式(Strategy) 、模板方法(TemplateMethod)、访问者模式(Visitor)。 
  了解了以上还远远不够,下面我们就来了解一下23种设计模式之一的单例模式。单例模式对我们开发者来说是再熟悉不过了。单例模式又分为饿汉式(线程安全,调用效率高。但是不能延时加载)、懒汉式(线程安全,调用效率低。可以延时加载)、双重检测锁(由于此模式偶尔会出现问题,不建议使用)、静态内部类式(线程安全,调用效率高。可以延时加载)、枚举单例(线程安全,调用效率高。不能延时加载)。单例模式的优点是:减少系统开销。我们经常使用的是饿汉式和懒汉式这两种。我们先来说一下饿汉式,饿这个字我想大家都知道啥意思,举个例子:当你很饿的时候你会去挑选你喜欢的食物吗?当然不会。当你很饿的时候,恰好发现有一些食物,此时的你不管是否是自己喜欢的食物,只要能充饥你都会去吃的。饿汉式模式也是一样,不论是否使用,先创建一个实例再说。缺点就是如果只加载本类,而不去调用getSingleton()这个方法的话,将会造成资源的浪费。因为一开始上来不论分说的先创建实例,这样很容易造成资源浪费。

public class Singleton {

private static Singleton singleton = new Singleton();public Singleton() {
}public static Singleton getSingleton() {    return singleton;
}

}

  懒汉式则就不同了,懒汉式就好比你不是很饿,此时的你很困正在床上休息,不论旁边的人如何喊你吃东西,只要不是自己特别喜欢吃的,你都懒得起来去吃,当听到有你喜欢吃的东西的时候此时的你可能会去品尝一下。懒汉式就是这样,不调用就不实例化。虽然解决了资源的浪费,但是由于每次调用getSingleton() 时都要同步,造成并发效率特别低。也许有人会说我不会不加synchronized 这个关键字进行同步限制吗?但是这样做是不行的,如果并发量有点高的情况下容易造成多次实例化,比如说线程1和线程2调用了getSingleton()这个方法,当刚调用还没有来得及判断singleton是否为空是,此时线程1挂起了,然后当线程2执行到singleton = new Singleton2()时,线程2挂起,此时线程1又从刚刚挂起的地方执行,这样就导致被实例化了两次。如果加了synchronized 以后,即使线程1挂起,线程2也不会去执行,直到线程1执行完,线程2才会去执行。

public class Singleton2 {

private static Singleton2 singleton;public Singleton2() {
}public static synchronized Singleton2 getSingleton() {    if (singleton==null){
        singleton = new Singleton2();
    }    return singleton;
}

}

  双重检测锁,顾名思义就是多次检测,这个模式将同步内容放到if里面,这样做提高了执行效率,没有必要每次获取对象时都要进行同步,只有第一次才会同步,以后每次都不需要。由于编译器优化问题此模式不建议使用。

public class Singleton3 {

private static Singleton3 singleton=null;public Singleton3() {
}public static Singleton3 getSingleton() {    if (singleton==null){
        Singleton3 st;        synchronized (Singleton3.class){
            st = singleton;            if (st==null){                synchronized (Singleton3.class){                    if (st==null){
                        st = new Singleton3();
                    }
                }
                singleton = st;
            }
        }
    }    return singleton;
}

}

  静态内部类模式,里面会用到final 这个关键字,static final 的作用就是防止被改变。这样获取到的空间地址永远是不会改变的,这样就会保证只有一个实例存在,而且是线程安全的。具备有高并发和延时加载的优势。

public class Singleton4 {

private static class SingletonDemo{    private static final Singleton4 singleton = new Singleton4();
}public Singleton4() {
}public static Singleton4 getSingleton() {    return SingletonDemo.singleton;
}

}

  枚举单例,枚举本身就是单例,缺点就是没有延时加载。

public enum Singleton5 {

SINGLETON;

}

  基于以上五种单例模式我们应该如何选择呢?如果是单例对象,占用资源较少,而且又不需要延时加载的话枚举式好于饿汉式。如果是单例对象,占用资源较大,而且需要延时加载的话静态内部类好于懒汉式。单例模式就到此结束了,平时我们使用的Application里面就涉及有单例模式。
  今天我们就先介绍单例模式,剩下的其他模式我们后面在一一分析。
http://www.apkbus.com/thread-282214-1-1.html

 原文链接:http://www.apkbus.com/blog-852316-68540.html

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消