• Head First 设计模式笔记(第四章 工厂模式 & 第五章 单例模式)


    第四章工厂模式 p109~147, 第五章单例模式 p148~189.

    概述

    工厂模式将类实例化集中化了. 代码变为Pizza pizza = PizaFactory.Create("SomePizzaType");
    单例模式使得类保持一个实例.

    工厂模式

    多个类具有同样的行为, 类之间的实现又有一些差异. 求同存异, 这就需要我们抽象出来一些接口, 接口是共同的, 接口内的实现是有差异的.

    共同的接口, 是让我们可以把这些类可以当作同一种类型进行处理, 增加了代码的统一性, 减少类似冗余代码的产生.

    这时, 类的构建就成为一个问题, 一般来说, 将字符串和类映射起来, BaseClass instance = ClassFactory.Create("ClassType");, 觉得字符串不安全, 可以使用枚举.

    本质上来说, 就是将一个If Else的类创建过程, 搬到了一个类中去实现.

    对依赖的影响
    使用者不应该依赖具体的类, 也就是使用者的代码中不应该出现SomeType instance = new SomeType();, 这样使用者就依赖这个具体的类. 如果这个类有变化, 如某个方法(非接口的方法)不再使用了, 或者调整参数了, 那么所有的使用者也要发生改变, 这样是不稳定的.

    使用者应该依赖接口,BaseClass instance = ClassFactory.Create("ClassType");, 这样就是按接口使用, 接口一般来说是不会改变的. 同时, 对于接口的实现要求也比较高, 最好一开始就设计好, 不会改变.

    接口对于扩展大有帮助, 有了接口后, 只要接口满足要求, 再新增一种类型就很轻松.

    使用工厂模式前

    使用工厂模式后

    单例模式

    维持一个独一无二的实例.

    经典单例

    public class Singleton1 {
        private static Singleton1 uniqueInstance;
    
        private Singleton1() {
        }
    
        public static Singleton1 getInstance() {
            if (uniqueInstance == null) {
                uniqueInstance = new Singleton1();
            }
            return uniqueInstance;
        }
    }
    

    线程不安全, 多线程下无法保持一个实例.

    经典单例加锁

    public class Singleton2 {
        private static Singleton2 uniqueInstance;
    
        private Singleton2() {
        }
    
        public static synchronized Singleton2 getInstance() {
            if (uniqueInstance == null) {
                uniqueInstance = new Singleton2();
            }
            return uniqueInstance;
        }
    }
    

    在方法上加了synchronized, 这是给方法加锁, 在每次调用该方法前需要检查锁, 一次只允许一个线程访问, 其它线程等待.
    锁会降低这个方法的性能.

    静态创建

    public class Singleton3 {
        private static Singleton3 uniqueInstance = new Singleton3();
    
        private Singleton3() {
        }
    
        public static Singleton3 getInstance() {
            return uniqueInstance;
        }
    }
    

    在JVM初始化时进行创建, 能够保证单例的唯一性, 缺点是占用内存, 占用启动时间.

    经典模式 + 单次锁

    public class Singleton4 {
        private static Singleton4 uniqueInstance;
    
        private Singleton4() {
        }
    
        public static Singleton4 getInstance() {
            if (uniqueInstance == null) {
                synchronized (Singleton4.class) {
                    if (uniqueInstance == null) {
                        uniqueInstance = new Singleton4();
                    }
                }
            }
            return uniqueInstance;
        }
    }
    

    由于经典模式加锁影响性能, 其实只需要创建实例的那一次才需要加锁, 所以就有这种单次锁的情况. 在实例创建之后, 先进行一个If判断, 不会进入加锁的代码片段, If判断的开销远小于锁的开销. 所以性能大幅提升.

    现实场景

    工厂模式

    这个是我日常用的最多的模式, 简单自然.

    单例模式

    用的少, 日常都是用静态方法或者属性才完成, 很少写单例.

  • 相关阅读:
    由于扩展配置问题而无法提供您请求的页面。如果该页面是脚本,请添加处理程序。
    浅析C#中ASP.NET页面的生存周期
    IIS:连接数、并发连接数、最大并发工作线程数、应用程序池的队列长度、应用程序池的最大工作进程数详解
    c#.net 生成清晰缩略图
    类序列化
    jQuery Validate验证框架使用
    XML序列化/反序列化数据库形式保存和读取。
    有关IT的小笑话
    百度富文本编辑器的使用!
    存储过程的使用
  • 原文地址:https://www.cnblogs.com/winwink/p/HeadFirstPattern_P3_Factory-Singleton.html
Copyright © 2020-2023  润新知