《设计模式一》单例模式和策略模式

1.1 单例模式-singleton

  • Spring的Bean工厂就是单例模式,项目中自己写的情况越来越少

1.1.1 工程中最常用版本-饿汉式

/**
 * 优点:线程安全
 * 缺点:不管用到与否,类装载时就完成实例化
 */
public class Singleton_01 {
    private static final Singleton_01 INSTANCE = new Singleton_01();

    private Singleton_01() {};

    public static Singleton_01 getInstance() {
        return INSTANCE;
    }
    public static void main(String[] args) {
        Singleton_01 m1 = Singleton_01.getInstance();
        Singleton_01 m2 = Singleton_01.getInstance();
        System.out.println(m1 == m2);
    }
}

1.1.2 双重锁检查-懒汉式

/**
 * 完美版本
 * 缺点:加锁带来效率下降
 * 优点:volatile禁止指令重排序,防止半初始化现象。
 * 优点:双重检查保证锁的粒度更小,且消除重复new对象的问题
 */
public class Singleton_02 {
    private static volatile Singleton_02 INSTANCE; //JIT

    private Singleton_02() {
    }

    public static Singleton_02 getInstance() {
        if (INSTANCE == null) {
            synchronized (Singleton_02.class) {
            // 第二次检查如果其他线程完成了初始化,其他线程无法进入
                if(INSTANCE == null) {
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    INSTANCE = new Singleton_02();
                }
            }
        }
        return INSTANCE;
    }
}

1.1.3 完美版本,但不直观

/**
 * 不仅可以解决线程同步,还可以防止反序列化。
 */
public enum Singleton_03 {

    INSTANCE;
    
    public static void main(String[] args) {
        for(int i=0; i<100; i++) {
            new Thread(()->{
               System.out.println(Singleton_03.INSTANCE.hashCode());
            }).start();
        }
    }
}

1.2 策略模式-Strategy

  • Java的Comparator接口,该接口只有一个抽象方法compare(T o1,T o2)就是策略模式的一个应用;

修改关闭,扩展开放

  • 实现排序方法,自己实现比较器传入,就是不同的策略传入,实现可扩展性,策略模式是封装的做一件事的不同的方式

1.2.1 Java的Comparator接口策略分析

  1. 策略:这里是比较策略,类比其他的比如售卖策略等
public interface Comparator<T> {
    int compare(T o1,T o2);
}
  1. 具体策略实现:这里定义根据对象的id来比较。类比售货打八折销售,满减等策略
 Comparator<User> comparator = new Comparator<User>() {
        @Override
        public int compare(User o1,User o2) {
              return o1.getId() - o2.getId();
        }
 };
  1. 应用策略:事先定义好策略应用
// 比如list的sort方法,需要传入比较策略
public static void main(String[] args) {
        List<User> l = new ArrayList<>();
        l.add(new User(2,"zhangsan","123","aaaa"));
        l.add(new User(3,"aaaa"));
        l.add(new User(1,"aaaa"));

        
        Comparator<User> comparator = new Comparator<User>() {
            @Override
            public int compare(User o1,User o2) {
                return o1.getId()-o2.getId();
            }
        };

        l.sort(comparator);

    }
    
// list的sort方法对比较策略的应用,事实上是用泛型接收具体类型
    default void sort(Comparator<? super E> c) {
        Object[] a = this.toArray();
        Arrays.sort(a,(Comparator) c);
        ListIterator<E> i = this.listIterator();
        for (Object e : a) {
            i.next();
            i.set((E) e);
        }
    }
  • 策略模式的实质是把具体的实现策略抽离出来,达到可扩展的目的,比如要进行比较,那么比较策略我们自己指定,“比较”动作可以识别我们传入的策略,和多态有点相似

相关文章

什么是设计模式一套被反复使用、多数人知晓的、经过分类编目...
单一职责原则定义(Single Responsibility Principle,SRP)...
动态代理和CGLib代理分不清吗,看看这篇文章,写的非常好,强...
适配器模式将一个类的接口转换成客户期望的另一个接口,使得...
策略模式定义了一系列算法族,并封装在类中,它们之间可以互...
设计模式讲的是如何编写可扩展、可维护、可读的高质量代码,...