设计模式
笔者能力有限,总结有误的地方,请读者协作更正。需要了解更多,请阅读相关书籍。
能说出来解释清楚,最好能写出伪代码
23种设计模式分3类:创建型5种,结构型分7种,行为型11种
设计模式的6大原则:
- 总原则:开闭原则,对扩展开放,对修改关闭
- 单一职责,里氏替换,依赖倒转,接口隔离,最少知道,合成复用
1.单例模式8种
基本实现思路:保证JVM中只能创建一个该对象的实例。对频繁创建和销毁对象时使用;工具类使用;
实现步骤:
私有静态变量;私有构造方法;
静态方法,调用该方法,持有对象引用,返回该引用;引用为空,创建实例。
1)饿汉模式(静态常量)可用
public class Singleton {
private final static Singleton INSTANCE = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return INSTANCE;
}
优点:避免线程同步
缺点:类加载之后,对象就创建出来在哪里放着,不管用不用,没有懒加载效果,内存浪费。
2)饿汉式(静态代码块)可用
把对象的创建放在静态代码块中,优缺点和上面一样。
public class Singleton {
private static Singleton instance;
static {
instance = new Singleton();
}
private Singleton() {}
public class Singleton {
private static Singleton instance;
static {
instance = new Singleton();
}
private Singleton() {}
3)懒汉模式(线程不安全)不可用
把对象的创建放在方法中,需要用的时候在创建;能实现懒加载,存在线程不安全。
public class Singleton {
private static Singleton singleton;
private Singleton() {}
public static Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
4)懒汉模式(线程安全,同步方法)可用,不推荐
加锁,懒加载,线程安全,但是效率低
public class Singleton {
private static Singleton singleton;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
5)懒汉模式(线程安全,同步代码块)不可用
public class Singleton {
private static Singleton singleton;
private Singleton() {}
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
singleton = new Singleton();
}
}
线程安全,但是会产生多个实例;
6)双重检查(推荐用)
public class Singleton {
private static volatile Singleton singleton;
private Singleton() {}
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
} } }
return singleton;
}
}
进行了两次if (singleton == null)检查,这样就可以保证线程安全了。这样,实例化代码只用执行一次,后面再次访问时,判断if (singleton == null),直接return实例化对象。
优点:线程安全;延迟加载;效率较高。
7)静态内部类(推荐用)
public class Singleton
private Singleton() {}
private static class SingletonInstance {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonInstance.INSTANCE;
}
}
类的静态属性只会在第一次加载类的时候进行初始化,JVM能够帮我们保证线程安全,在进行初始化的时候,别的线程无法进入。
优点:线程安全,延迟加载,效率高。
8)枚举(推荐用)
public enum Singleton{
Instance;
private void EvenMethod(){
}
}
JDK1.5中添加的枚举来实现单例模式。
不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。
2.工厂方法
简单工厂方法
不同的类实现同一个接口,创建一个简单工厂来为这些类创建实例;
例如:发送短信,发送邮件,将发送抽取出来作为接口,建一个简单工厂来实现发送的实例,当然还有其它的写法。
工厂方法
简单工厂存在的问题,类的创建依赖于工厂类,想要修改程序就需要修改工厂,违背了闭包原则
工厂方法,扩展功能,直接增加工厂类。
3.抽象工厂
工厂方法中,一个工厂只能生产一种产品。重点在于产品,如果一个方法需要有大量的实现细节,很多代码需要围绕这个产品展开,推荐使用工厂方法。
抽象工厂中,一个工厂可以创建多种产品类,因为抽象工厂中有一堆的工厂方法,一个工厂方法返回对应的数据类型。重点在于数量,如果要求不同的产品线,保持接口一致,推荐使用抽象工厂方法。
4.代理模式
1)就是用另外一个类代替目标类的操作,同时能够提供额外的操作;
比如:房地产中介,客户,和房东就是一个代理模式;
- -地产中介 卖房,带客户看房,收取中介费
- -房东 卖房
- -客户 买房
2)分类:静态代理,和动态代理 spring中AOP应用了两种代理模式,ciglib动态代理,jdk动态代理 详解Spring的AOP?
1.1 静态代理
特点:实现和被代理这相同的接口,能够执行代理者相同的方法,添加额外的功能操作
缺点:一个目标对象就需要一个代理类,一个明星就需要一个经济人
复用性不高,不通用
1.2 动态代理
分为-->JDK代理 CGlib代理 -jdk动态代理
特点:实现相同的接口,执行目标对象的方法,能做额外的操作,
优点:一个代理类,能为很多目标类服务,解耦,高复用
缺点:只能处理事务,不具备通用性(日志,安全,权限等)
-CGlib动态代理
特点:执行目标对象的方法,能做额外的操作
优点:一个代理类,能为很多目标类服务,解耦,高复用,而且不需要实现接口,
1.3 Spring 生成代理对象
Spring整合了JDK代理和Cglib代理,
Jdk代理实现的是invocationHandler接口;Cglib实现的是MethodInterceptor接口
实现着两个接口,spring代理模式内部能够的自由切换。让代理模式复用性更高,使用更方便。
5.装饰器模式
装饰模式和代理模式很像,都是为了扩展功能,
装饰模式要求给一个对象动态的增加一些新的功能,要求装饰对象和被装饰对象实现共同的接口,装饰对象持有被装饰对象的引用。
6.策略模式
就是定义一系列的算法族,将每一个算法封装成独立的类,然后所有的类实现统一的接口,这些算法之间可以相互替换,每一个算法的变化不会影响到用户的使用。
需要设计一个接口,为一序列类提供统一的方法,多个实现类实现该接口,设计一个抽象类,提供辅助函数。
7.观察者模式
是一种一队多的关系,就像公众号和粉丝的关系;
当一个对象发生变化时候,其它依赖于该对象的类都会收到通知;
8.责任链模式
就是,有多个对象,每一个对象持有下一个对象的引用,形成一条链,请求在这条链上传递,直到被某一对象被处理,但是请求并不知道是哪一个对象处理了这个请求。
比喻:我去拜访元首,第一道安检,让我初始通行证;第二道安全,搜身;第三道安检,是否预约;每一次安检负责每一次安检的工作,所有的安检形成一条链,我作为一个对象在这条链上传递,安检不通过,抛异常。
更多建议: