首页 > 技术文章 > 设计模式笔记

henry829 2021-04-16 15:35 原文

设计模式

 

OOP面向对象编程七大原则

 开闭原则:对扩展开发,对修改关闭,尽量不要修改原来的代码

里氏替换原则:继承要保证父类的性质在子类中依然成立

依赖倒置原则:要面向接口编程

单一职责原则:控制类的粒度大小, 将对象解耦

接口隔离原则:为各个类建立需要的专用接口

迪米特原则:只和朋友交流,不与陌生人交谈

合成复用原则:先使用组合或者聚合等关联关系来实现,其次再考虑继承关系

单例模式

 饿汉式

// 饿汉式
public class Hungry {
    private Hungry() {

    }

    private static Hungry Hungry = new Hungry();

    public static Hungry getInstance() {
        return Hungry;
    }
}

 

懒汉式

{
    private LazyMan() {
        System.out.println(Thread.currentThread().getName());
    }
    // 使用volatile防止指令重排
    private static volatile LazyMan lazyMan;

    // 双重检测锁模式dcl懒汉式
    public static LazyMan getInstance() {
        if(lazyMan == null) {
            synchronized (LazyMan.class) {
                if(lazyMan == null) {
                    lazyMan = new LazyMan();
                }
            }

        }
        return lazyMan;
    }

    // 多线程并发
    public static void main(String[] args) {
        for (int i = 0; i <10; i++) {
            new Thread(()->{
                LazyMan.getInstance();
            },String.valueOf(i)).start();
        }
    }

}

 

 静态内部类

public class Holder {
    private Holder() {

    }

    public static class InnerClass {
        private static final Holder HOLDER = new Holder();
    }

    public static Holder getInstance() {
        return InnerClass.HOLDER;
    }
}

单例不安全可以通过反射破坏

// 懒汉式单例
public class LazyMan {
    private LazyMan() {
        System.out.println(Thread.currentThread().getName());
    }

    private static LazyMan lazyMan;

    public static LazyMan getInstance() {
        if (lazyMan == null) {
            synchronized (LazyMan.class) {
                if (lazyMan == null) {
                    lazyMan = new LazyMan();
                }
            }
        }

        return lazyMan;
    }

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        LazyMan instance = LazyMan.getInstance();
        LazyMan instance2 = LazyMan.getInstance();
        System.out.println(instance == instance2); // 正常,true

        Constructor<LazyMan> declaredConstructor = LazyMan.class.getDeclaredConstructor(null);
        // 设置在使用构造器的时候不执行权限检查,破坏程序的封装性和安全性
        declaredConstructor.setAccessible(true);
        LazyMan instance3 = declaredConstructor.newInstance();
        LazyMan instance4 = declaredConstructor.newInstance();
        //问题1:
        System.out.println(instance == instance3); // false
     // 问题2
     System.out.println(instance == instance3); // false
 } }

问题1解决,修改构造函数,加同步锁

private LazyMan() {
    synchronized (LazyMan.class) {
        if (lazyMan != null) {
            throw new RuntimeException("error");
        }
    }
}

问题2,解决

private static boolean henry = false;
private LazyMan() {
    synchronized (LazyMan.class) {
        if (!henry) {
            henry = true;
        } else {
            throw new RuntimeException("error");
        }
    }
}

 

枚举

public enum EnumSingle {
    INSTANCE;

    public static EnumSingle getInstance() {
        return INSTANCE;
    }

}
class Test {
    public static void main(String[] args) throws Exception {
        EnumSingle instance1 = EnumSingle.getInstance();
        Constructor<EnumSingle> constructor = EnumSingle.class.getDeclaredConstructor(null);
        constructor.setAccessible(true);
        EnumSingle instance2 = constructor.newInstance();
        // java.lang.NoSuchMethodException
        System.out.println(instance1 == instance2);
    }
}

 

 反编译EnumSingle.class,发现也有个无参构造

 

使用Jad程序EnumSinle.class变为java文件,实际上是有个两个参数的构造

 

 修改代码,才会报错反射不能破坏枚举单例

        Constructor<EnumSingle> constructor = EnumSingle.class.getDeclaredConstructor(String.class,int.class);

 

工厂模式

 简单工厂模式

public interface Car {
    public void name();
}

public class Odi implements Car{
    @Override
    public void name() {
        System.out.println("奥迪");
    }
}


public class Tesla implements Car{
    @Override
    public void name() {
        System.out.println("特斯拉");
    }
}

静态工厂

// 静态工厂模式
// 增加一个新的,必须要修改代码
public class CarFactory {

    // 方法1
    public static Car getCar(String name) {
        if(name.equals("奥迪")) {
            return new Odi();
        } else if(name.equals("特斯拉")) {
            return new Tesla();
        } else {
            return null;
        }
    }

    // 方法2
    public static Car getOdi() {
        return new Odi();
    }
    public static Car getTesla() {
        return new Tesla();
    }
}

消费者

// 使用具体的实现类买车
Car car = new Odi();
// 使用工厂
Car car1 = CarFactory.getCar("奥迪");
car1.name();
           

 

工厂方法模式

// 工厂方法模式
public interface CarFactory {
    public Car getCar();
}

public class OdiFactory implements CarFactory{
    @Override
    public Car getCar() {
        return new Odi();
    }
}

public class TeslaFactory implements CarFactory{
@Override
public Car getCar() {
return new Tesla();
}
}

消费者从对应的OdiFactory或者TeslaFactory

 Car car = new OdiFactory().getCar();
 Car car1 = new TeslaFactory().getCar();

在结构复杂,代码复杂度上简单工厂模式好

根据开闭设计原则,工厂方法模式符合

 

抽象工厂模式

推荐阅读