设计原则

单一原则                指一个类只描述一个事物,方法只做一件事(高内聚,低耦合)

开闭原则                对扩展开放 对修改关闭;不修改原来的代码,实现一个热插拔的效果

里氏替换原则            程序中的父类参数都可以使用子类替代 实现类似的效果

迪米特法则            最少知道原则(不要和陌生人说话);一个实体类应尽量少的和其他实体之间发生相互做

用,使系统模块相互独立

接口隔离原则            每个接口功能要单一 具体 不能太复杂 太多

依赖倒置原则            我们的程序应该依赖于抽象 而非依赖于具象;针对接口编程,依赖于抽象而不依赖具体

设计模式分类

创建型模式(Creational Patterns)

结构型模式(Structural Patterns)

行为型模式(Behavioral Patterns)

序号

模式 & 描述

包括

1

创建型模式(5种)
这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象。这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活。

  • 工厂模式(Factory Pattern)
  • 抽象工厂模式(Abstract Factory Pattern)
  • 单例模式(Singleton Pattern)
  • 建造者模式(Builder Pattern)
  • 原型模式(Prototype Pattern)

2

结构型模式(8种)
这些设计模式关注类和对象的组合。继承的概念被用来组合接口和定义组合对象获得新功能的方式。

  • 适配器模式(Adapter Pattern)
  • 桥接模式(Bridge Pattern)
  • 过滤器模式(Filter、Criteria Pattern)
  • 组合模式(Composite Pattern)
  • 装饰器模式(Decorator Pattern)
  • 外观模式(Facade Pattern)
  • 享元模式(Flyweight Pattern)
  • 代理模式(Proxy Pattern)

3

行为型模式(10种)
这些设计模式特别关注对象之间的通信

  • 责任链模式(Chain of Responsibility Pattern)
  • 命令模式(Command Pattern)
  • 解释器模式(Interpreter Pattern)
  • 迭代器模式(Iterator Pattern)
  • 中介者模式(Mediator Pattern)
  • 备忘录模式(Memento Pattern)
  • 观察者模式(Observer Pattern)
  • 状态模式(State Pattern)
  • 空对象模式(Null Object Pattern)
  • 策略模式(Strategy Pattern)
  • 模板模式(Template Pattern)
  • 访问者模式(Visitor Pattern)

常用设计模式

单例模式

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。属于创建型设计模式

解决的问题:一个类只有唯一实例的需求

满足的条件: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代理。

本该自己做的事情,交给其他人去做。

静态代理:代理类和目标类是一一对应的(一个目标类对应一个代理类)

缺点:会产生大量的代理类,当接口增加方法时,所有的代理类都需要维护

动态代理:代理类是动态生成的。