设计原则
单一原则 指一个类只描述一个事物,方法只做一件事(高内聚,低耦合)
开闭原则 对扩展开放 对修改关闭;不修改原来的代码,实现一个热插拔的效果
里氏替换原则 程序中的父类参数都可以使用子类替代 实现类似的效果
迪米特法则 最少知道原则(不要和陌生人说话);一个实体类应尽量少的和其他实体之间发生相互做
用,使系统模块相互独立
接口隔离原则 每个接口功能要单一 具体 不能太复杂 太多
依赖倒置原则 我们的程序应该依赖于抽象 而非依赖于具象;针对接口编程,依赖于抽象而不依赖具体
设计模式分类
创建型模式(Creational Patterns)
结构型模式(Structural Patterns)
行为型模式(Behavioral Patterns)
序号 |
模式 & 描述 |
包括 |
1 |
创建型模式(5种) |
|
2 |
结构型模式(8种) |
|
3 |
行为型模式(10种) |
|
常用设计模式
单例模式
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。属于创建型设计模式
解决的问题:一个类只有唯一实例的需求
满足的条件:1.有私有化的静态变量 2.有私有化的构造方法 3.有一个静态的方法
思考题:单例模式的四种实现?
懒汉式、饿汉式、双重校验锁(DCL)、静态内部类
单例模式的优点:
1.单例模式可以保证内存里只有一个实例,减少了内存的开销。
2.可以避免对资源的多重占用。
3.单例模式设置全局访问点,可以优化和共享资源的访问
单例模式的缺点:
1.单例模式一般没有接口,扩展困难。如果要扩展,则除了修改原来的代码,没有第二种途径,违背开闭原则。
2.在并发测试中,单例模式不利于代码调试。在调试过程中,如果单例中的代码没有执行完,也不能模拟生成一个新的对象。
3.单例模式的功能代码通常写在一个类中,如果功能设计不合理,则很容易违背单一职责原则。
实现
懒汉式:特点是类加载时没有生成单例,只有当第一次调用 getlnstance 方法时, 才去创建这个单例;
线程不安全:
public class Singleton { private static Singleton instance; private Singleton (){} public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
线程安全: 关键字synchronized
public class Singleton { private static Singleton instance; private Singleton (){} public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
饿汉式:特点是类一旦加载就创建一个单例,保证在调用 getInstance 方法之前单例已经存在了。
public class HungrySingleton { private static final HungrySingleton instance = new HungrySingleton(); private HungrySingleton() { } public static HungrySingleton getInstance() { return instance; } }
双检锁/双重校验锁(DCL,即 double-checked locking):采用双锁机制,安全且在多线程情况下能保持高性能。
public class Singleton { private volatile static Singleton singleton; private Singleton (){} public static Singleton getSingleton() { if (singleton == null) { synchronized (Singleton.class) { if (singleton == null) { singleton = new Singleton(); } } } return singleton; } }
登记式/静态内部类:能达到双检锁方式一样的功效,但实现更简单。对静态域使用延迟初始化,应使用这种方式而不是双检锁方式。这种方式只适用于静态域的情况,双检锁方式可在实例域需要延迟初始化时使用。
外部类加载时并不需要立即去加载内部类,内部类不被加载则不去初始化instance,只有第一次调用getInstance的时候才会初始化
public class Singleton { private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } private Singleton (){} public static final Singleton getInstance() { return SingletonHolder.INSTANCE; } }
工厂模式
提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。属于创建型
解决的问题:隐藏对象创建的细节,用于创建不同的类的对象的
优点:
1、一个调用者想创建一个对象,只要知道其名称就可以了。
2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。
3、屏蔽产品的具体实现,调用者只关心产品的接口。
缺点:
每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。
代理模式
分为静态代理和动态代理,动态代理又有jdk代理和cglib代理。
本该自己做的事情,交给其他人去做。
静态代理:代理类和目标类是一一对应的(一个目标类对应一个代理类)
缺点:会产生大量的代理类,当接口增加方法时,所有的代理类都需要维护
动态代理:代理类是动态生成的。