设计模式(一) 单例模式

Hello

      设计学习应用,好记性不如烂笔头,强调不是学习和小试牛刀,通过几遍文章资料,通过几段固定的代码就可以把设计模式的思想掌握的很好(当然不排除在座的各位中有骨骼精奇万中无一的奇才,明显本座不是),主要将设计的思维领悟,能应用到自己的项目,或者是工作环境中,不然永远是虚把式,提升自我的思考层次.

设计模式,许多在代码层级,逻辑上都是有套路的,更多我们需要了解知道模式使用的场景、意义, 思维思考方式的转换.

以上废话都是鼓励自己用的,请大家跳过即可.

下面是将要逐步学习应用的 GOF23"四人帮" 的设计模式.

模式分类

创建型模式 :  ↓↓↓

    --单例模式,工厂模式,抽象工厂模式,建造者模式,原型模式.

结构型模式 :  ↓↓↓
    --适配器模式,桥接模式,装饰模式,组合模式,外观模式,享元模式,代理模式.

行为型模式 :  ↓↓↓

    --模版方法模式,命令模式,迭代器模式,观察者模式,中介者模式,备忘录模式,解释器模式,状态模式,
      策略模式,职责模式,访问者模式.

---------------------------以下开始本编内容---------------------------

单例模式

核心作用: 保证一个类中只有一个实例,并提供一个全局访问点.

只有一个实例,减少系统的开销,比如配置文件,其他API的依赖等,运行时只需要在内存中生成一份对象,而不需要每次去获取的时候new一个对象,多一份对象产生. 可以在全局设置访问点,优化资源访问.

朋友送我一只小狗,隔壁小妹妹想摸摸,我就拿给她摸摸,她很开心.楼上小姐姐想玩玩,我就抱给她玩玩,她也很开心.楼下大爷自己去抓狗溜,没有找我,当然是抓不到的了.

五种常见的方式

饿汉式

项目开始,不管后面会不会使用该类,类加载器都会加载该类

线程安全,调用率高,不能懒加载

1.需要有一个private的构造器,其他类无法调用其构造器初始化

2.还需要一个private static类变量并初始化

3.另外提供一个对外的public访问点,其他类只能在此处获取该对象

public class SingleZone {
    //类加载器加载,是线程安全的
    private static SingleZone single=new SingleZone();

    private SingleZone() {
    }

    public static SingleZone getSingle(){
        return single;
    }
}

懒汉式

线程安全,调用率不高,可以懒加载

1.需要有一个private的构造器,其他类无法调用其构造器初始化

2.还需要一个private static类变量不初始化

3.另外提供一个对外的public访问点,其他类只能在此处获取该对象

4.多线程情况下,在全局访问点(getSingle()方法)加上synchronized修饰,自然的并发效率会低一点

public class SingleOne {
    //定义不初始化
    private static SingleOne single;

    private SingleOne() {
    }

    //需要的时候才会初始化对象
    public synchronized static SingleOne getSingle(){
        if (single==null){
            single=new SingleOne();
        }
        return single;
    }
}

双重检测锁式(了解即可,参考)

public class SingleTwo {
    private static SingleTwo singleTwo=null;

    private SingleTwo(){

    }

    public SingleTwo getSingleTwo(){
        if (singleTwo==null){
            SingleTwo singleTwo1;
            synchronized (SingleTwo.class){
                singleTwo1=singleTwo;
                if (singleTwo1==null){
                    synchronized (SingleTwo.class){
                        if(singleTwo1==null){
                            singleTwo1=new SingleTwo();
                        }
                    }
                }
                singleTwo=singleTwo1;
            }
        }

        return singleTwo;
    }
}

静态内部类式

线程安全,调用率高,可以延迟加载

1.外部类没有static定义和初始化,不会立即加载对象

2.只有需要时调用访问点,才能获取到对象,加载类是线程安全的

3.内部类有static (final)修饰,在内存内确保只有一份对象,只能被赋值一次,线程安全

4.具备并发,懒加载的优点

public class SingleThree {

    private SingleThree(){

    }

    //通过静态内部类初始化 SingleThree外部类
    private static class SingleInnerClass{
        private static final SingleThree singleThree=new SingleThree();
    }

    //需要的时候调用即可
    public SingleThree getSingleThree(){
        return SingleInnerClass.singleThree;
    }
}

枚举单例式

枚举元素本身是单例模式,没有懒加载,在JVM下,避免反射,反序列化的影响.

每一个枚举实例都是static final类型,表示只能被实例化一次,Java规范中规定,每一个枚举类型极其定义的枚举变量在JVM中都是唯一的,反序列化后的实例也会和之前被序列化的对象实例相同,保证枚举序列化单例.

public enum SingleFour {
    INSTANCE;

    //private Object ...
    
    //构造器
    SingleFour() {

    }

    //自定义操作
    public Object operation(){
        return "object";
    }
}

---------------------------------------------------------------------------------------------

猜你喜欢

转载自my.oschina.net/u/3829444/blog/1812282