设计模式讲解

设计原则

在此向各位说声抱歉,此文章还在编辑完善中,此文主要展示demo

单一职责原则

一个类中应当只有一个引起它变化的原因,即一个类应当只有一个职责

优点

  • 降低类的复杂性

  • 提高类的可读性

  • 提高代码的可维护性和复用性

  • 降低因变更引起的风险

里氏替换原则

在面向对象的语言中,继承是必不可少的

尽可能的不要覆盖重写父类方法

优点

  • 代码共享,减少创建类的工作,每个类都有父类的方法和属性
  • 提高代码的可重用性
  • 提高代码的可扩展行
  • 提高产品或项目的开发性

缺点

  • 继承是入侵式的,只要继承,就必须拥有父类的属性和方法
  • 降低代码的灵活性,子类必须拥有父类的方法和属性,是子类受限
  • 增强了耦合性,当父类属性和方法发生变化是,必须考虑子类的修改,可能发生大片代码的重构

依赖倒置原则

面向接口编程

接口隔离原则

接口尽量的设计为细粒度

迪米特法则

降低耦合,不要在局部变量中引入新的类

开闭原则

对扩展开放,对修改关闭

创建型模式

创建型模式是用来创建对象的模式,抽象了实例化的过程,所有的创建型模式都有两个主要功能

  • 将系统使用的具体类的信息封装起来
  • 隐藏类的实例是如何被创建和组织

单例模式

/**
 * 通过添加readResolve方法,覆盖反序列化出来的对象,防止通过反序列化的方式破坏单例
 * 通过反序列化,还是会创建两次,但是因为此方法覆盖上一个创建的对象,实现单例不被破坏,相对安全
 * 之前反序列化创建的对象会被GC回收
 * @return
 */
private Object readResolve(){
    return hungryStaticSingleton;
}

懒汉模式

  • 简单懒汉模式

    public class LazySimpleSingleton {
        private LazySimpleSingleton(){}
        private static LazySimpleSingleton lazySimpleSingleton = null;
        public synchronized static LazySimpleSingleton getInstance(){
            if(lazySimpleSingleton == null){
                lazySimpleSingleton = new LazySimpleSingleton();
            }
            return lazySimpleSingleton;
        }
    }
    
  • 静态内部类模式

    public class LazyInnerClassSingleton {
        private LazyInnerClassSingleton(){
            if(LazyHolder.LAZY != null){
                throw new RuntimeException("不允许构建多个实例");
            }
        }
        public static final LazyInnerClassSingleton getInstance(){
            return LazyHolder.LAZY;
        }
        private static class LazyHolder{
            private static final LazyInnerClassSingleton LAZY = new LazyInnerClassSingleton();
        }
    }
    
  • 双重锁模式

    public class LazyDoubleCheckSingleton {
        private LazyDoubleCheckSingleton(){}
        private volatile static LazyDoubleCheckSingleton lazyDoubleCheckSingleton;
        public static LazyDoubleCheckSingleton getInstance(){
            if(lazyDoubleCheckSingleton == null){
                synchronized (LazyDoubleCheckSingleton.class){
                    if(lazyDoubleCheckSingleton == null){
                        lazyDoubleCheckSingleton = new LazyDoubleCheckSingleton();
                    }
                }
            }
            return lazyDoubleCheckSingleton;
        }
    }
    

饿汉模式

  • 饿汉模式

  • /**
     * 饿汉式单例
     */
    public class HungrySingleton {
        private static final HungrySingleton hungrySingleton = new HungrySingleton();
        private HungrySingleton(){}
        public HungrySingleton getInstance() {
            return hungrySingleton;
        }
    }
    
  • 静态代码块

    public class HungryStaticSingleton {
        private HungryStaticSingleton(){}
        private static final HungryStaticSingleton hungryStaticSingleton;
        static {
            hungryStaticSingleton = new HungryStaticSingleton();
        }
        public static HungryStaticSingleton getInstance(){
            return hungryStaticSingleton;
        }
    }
    

容器式单例

public class ContainerSingleton {
    private ContainerSingleton(){}
    private static volatile Map<String, Object> ioc = new HashMap<>();
    public static void put(String name, Object obj){
        if(!ioc.containsKey(name)){
            synchronized (ioc){
                if(!ioc.containsKey(name)){
                    try {
                        ioc.put(name, obj);
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    public static Object get(String name){
        return ioc.get(name);
    }
}

注册式单例

  • 枚举单例

    枚举从底层屏蔽各种破坏单例的效验

    public enum EnumSingleton {
        INSTANCE;
        private Object data;
        public Object getData(){
            return data;
        }
        public static EnumSingleton getInstance(){
            return INSTANCE;
        }
    }
    

threadLocal 伪单例

伪单例,只能在同一个线程内单例,多个线程同时使用时不能保持单例

public class ThreadLocalSingleton {
    private ThreadLocalSingleton(){}
    private static final ThreadLocal<ThreadLocalSingleton> threadLocal = new ThreadLocal<ThreadLocalSingleton>(){
        public ThreadLocalSingleton initialValue(){
            return new ThreadLocalSingleton();
        }
    };
    public static ThreadLocalSingleton getInstance() {
        return threadLocal.get();
    }
}

工厂模式

简单工厂(不属于23中设计模式)

由一个工厂类,一个生产线接口多个生产线实体的实现类组成

在工厂内部根据条件创建指定的生产线实现类,返回生产线接口

通过生产线接口调用执行方法

创建流程

  • 创建生产线接口
  • 创建生产线实体
  • 创建工厂实体,根据条件判断创建生产线实体返回生产线接口
//创建生产线接口
public interface IPhone {
    public void start();
    public void shutdown();
}
//创建生产线实体
public class HwPhone implements IPhone {
    @Override
    public void start() {
        System.out.println("华为手机开机");
    }
    @Override
    public void shutdown() {
        System.out.println("华为手机关机");
    }
}
//创建生产线实体
public class XmPhone implements IPhone {
    @Override
    public void start() {
        System.out.println("小米手机开机");
    }
    @Override
    public void shutdown() {
        System.out.println("小米手机关机");
    }
}
//创建简单工厂
public class Factory {
  	//name仅代表一个变量,也可以用其他,比如class.getName等
    public IPhone create(String name){
        if(name == "hw"){
            return new HwPhone();
        }else if(name == "xm"){
            return new XmPhone();
        }else{
            return null;
        }
    }
}
//测试
public class Test {
    private static Factory factory = new Factory();
    public static void main(String[] args) {
        IPhone iPhone = factory.create("hw");
        iPhone.start();
        iPhone.shutdown();
        IPhone iPhone1 = factory.create("xm");
        iPhone1.start();
        iPhone1.shutdown();
    }
}
简单工厂UML图

工厂方法

由一个工厂接口,多个实体工厂,一个生产线接口多个生产线实体的实现类组成

创建流程

  • 生产线接口
  • 创建工厂接口
  • 创建生产线实体
  • 创建工厂实体,根据不同的工厂实体创建不同的生产线实体,返回生产线接口
//创建生产线接口
public interface IPhone {
    public void start();
    public void shutdown();
}
//创建工厂接口
public interface IFactory {
    public IPhone create();
}
//创建生产线实体
public class HwPhone implements IPhone {
    @Override
    public void start() {
        System.out.println("华为手机开机");
    }
    @Override
    public void shutdown() {
        System.out.println("华为手机关机");
    }
}
//创建生产线实体
public class XmPhone implements IPhone {
    @Override
    public void start() {
        System.out.println("小米手机开机");
    }
    @Override
    public void shutdown() {
        System.out.println("小米手机关机");
    }
}
//创建工厂实体
public class HwFactory implements IFactory {
    @Override
    public IPhone create() {
        return new HwPhone();
    }
}
//创建工厂实体
public class XmFactory implements IFactory {
    @Override
    public IPhone create() {
        return new XmPhone();
    }
}
//测试
public class Test {
    private static IFactory hwFactory = new HwFactory();
    private static IFactory xmFactory = new XmFactory();
    public static void main(String[] args) {
        IPhone hw = hwFactory.create();
        hw.start();
        hw.shutdown();
        IPhone xm = xmFactory.create();
        xm.start();
        xm.shutdown();
    }
}
工厂方法UML图

抽象工厂

由一个工厂接口,多个实体工厂,多个生产线接口对应的多个生产线实体的实现类组成

创建流程

  • 创建多个生产线接口
  • 创建工厂接口
  • 创建生产线实体
  • 创建多个工厂实体,根据工厂类型创建对应的生产线实体返回对应的生产线接口
//创建生产线接口
public interface IPhone {
    public void start();
    public void shutdown();
}
//创建生产线接口
public interface IWifi {
    public void start();
    public void shutdown();
}
//创建工厂接口
public interface IFactory {
    public IPhone create();
}
//创建生产线实体
public class HwPhone implements IPhone {
    @Override
    public void start() {
        System.out.println("华为手机开机");
    }
    @Override
    public void shutdown() {
        System.out.println("华为手机关机");
    }
}
//创建生产线实体
public class HwWifi implements IWifi {
    @Override
    public void start() {
        System.out.println("华为WIFI开机");
    }
    @Override
    public void shutdown() {
        System.out.println("华为WIFI关机");
    }
}
//创建生产线实体
public class XmPhone implements IPhone {
    @Override
    public void start() {
        System.out.println("小米手机开机");
    }
    @Override
    public void shutdown() {
        System.out.println("小米手机关机");
    }
}
//创建生产线实体
public class XmWifi implements IWifi {
    @Override
    public void start() {
        System.out.println("小米WIFI开机");
    }
    @Override
    public void shutdown() {
        System.out.println("小米WIFI关机");
    }
}
//创建工厂实体
public class HwFactory implements IFactory {
    @Override
    public IPhone createPhone() {
        return new HwPhone();
    }
    @Override
    public IWifi createWifi() {
        return new HwWifi();
    }
}
//创建工厂实体
public class XmFactory implements IFactory {
    @Override
    public IPhone createPhone() {
        return new XmPhone();
    }
    @Override
    public IWifi createWifi() {
        return new XmWifi();
    }
}
//测试
public class Test {
    private static IFactory hwFactory = new HwFactory();
    private static IFactory xmFactory = new XmFactory();
    public static void main(String[] args) {
        IPhone hwPhone = hwFactory.createPhone();
        hwPhone.start();
        hwPhone.shutdown();
        IWifi hwWifi = hwFactory.createWifi();
        hwWifi.start();
        hwWifi.shutdown();
        IPhone xmPhone = xmFactory.createPhone();
        xmPhone.start();
        xmPhone.shutdown();
        IWifi xmWifi = xmFactory.createWifi();
        xmWifi.start();
        xmWifi.shutdown();
    }
}
抽象工厂UML图

建造者模式-

原型模式

浅克隆

对象内部使用set对每一个参数赋值(对象传递的是内存地址,所以称之为浅克隆)

public class ShallowPrototype implements Cloneable{
    Random random;
    public ShallowPrototype() {
    }
    public Random getRandom() {
        return random;
    }
    public void setRandom(Random random) {
        this.random = random;
    }
    public ShallowPrototype clone() throws CloneNotSupportedException {
        return (ShallowPrototype)super.clone();
    }
}

深克隆

原型模式就是提供快速构建对象的方法,实现JDK的cloneable接口

需要使用字节码使用

public class DeepPrototype implements Serializable {
    Random random;
    public DeepPrototype() {
    }
    public Random getRandom() {
        return random;
    }
    public void setRandom(Random random) {
        this.random = random;
    }
    public DeepPrototype clone(){
        DeepPrototype deepPrototype = null;
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(this);
            byte[] bytes = bos.toByteArray();
            ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
            ObjectInputStream ois = new ObjectInputStream(bis);
            deepPrototype = (DeepPrototype) ois.readObject();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return deepPrototype;
    }
}

结构型模式

代理模式

静态代理

动态代理

动态代理实现原理(动态代理的对象必须实现接口)

  • 拿到被代理的引用,并获取他的所有接口(反射获取)
  • JDK Proxy类重新生成一个新的类,实现了被代理类的接口
  • 动态生成java代码,将增强逻辑加入的新的代码中(生成新的类,并存在所有的接口)
  • 编译成新的java代码的class文件
  • 加载并重新运行新的class,得到的类是全新的

目的,都是为了生成新的类,去实现增强代码的逻辑功能

JDK优劣:

  • 读取接口的信息
  • 必须实现一个接口,目标类相对复杂
  • 生成代理逻辑简单,但执行效率相对要低,因为每次都要反射动态调用

CGLib优劣:

  • 覆盖父类方法
  • 可以代理任何一个普通的类,没有任何要求
  • 生成代码逻辑更复杂,效率相对较高,生成一个包含了所有逻辑的FastClass,不再需要反射调用
  • 有个坑,不能代理final修饰的方法
  • JDK 动态代理实现
// 创建代理类
public class Factory implements InvocationHandler {
    private Object target;
    public Object getProxyInstance(Object target){
        this.target = target;
        Class<?> clazz = this.target.getClass();
        return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("前置增强。。。。。。");
        Object invoke = method.invoke(this.target, args); //返回的是方法执行后的结果集
        System.out.println("后置增强。。。。。。");
        return invoke;
    }
}
//创建接口
public interface IProduct {
    void find();
}
//创建实体类,继承接口
public class phone implements IProduct{
    public void find(){
        System.out.println("方法执行。。。。。。");
    }
}
//测试代码
public class Test {
    public static void main(String[] args) {
        Factory factory = new Factory();
        IProduct productProxy = (IProduct)factory.getProxyInstance(new phone());
        productProxy.find();
    }
}
  • cglib 动态代理实现

编写文档时未找到接口

实现 MethodInterceptor

实现intercept方法,根据参数进行设置

优点是代理类不需要实现接口,可以是普通的类,强转成对应的类即可代理

装饰模式

装饰器模式

模拟场景:一杯水,加一份糖加一块钱

//定义接口
public interface Water {
    String getMsg();
    int getPrice();
}
//定义基础类(一杯水)
public class BaseWater implements Water {
    @Override
    public String getMsg() {
        return "一杯白开水。";
    }
    @Override
    public int getPrice() {
        return 5;
    }
}
//定义装饰器
public class WaterDecortor implements Water {
    private Water water;
    public WaterDecortor(Water water) {
        this.water = water;
    }
    @Override
    public String getMsg() {
        return this.water.getMsg();
    }
    @Override
    public int getPrice() {
        return this.water.getPrice();
    }
}
//定义加糖
//继承定义的装饰器
public class CandyDecortor extends WaterDecortor{
    public CandyDecortor(Water water) {
        super(water);
    }
    @Override
    public String getMsg() {
        return super.getMsg() + "加一份糖,";
    }
    @Override
    public int getPrice() {
        return super.getPrice() + 2;
    }
}
//测试
public class Test {
    public static void main(String[] args) {
        Water water = new BaseWater();  //创建一杯水
        System.out.println(water.getMsg() + ":" + water.getPrice());
        water = new CandyDecortor(water); //给水加一份糖
        System.out.println(water.getMsg() + ":" + water.getPrice());
        water = new CandyDecortor(water); //再给水加一份糖
        System.out.println(water.getMsg() + ":" + water.getPrice());
    }
}
装饰器模式UML

适配器模式

将一个类的接口,转换成客户希望的另一种接口,使原本不兼容的类可以一起工作

Adapter类,通过继承 src类,实现 dst 类接口,完成src->dst的适配。k

//历史创建Vc220V
public class Vc220 {
    public int vc(){
        return 220;
    }
}
//新规范接口DC5V
public interface IDc5 {
    public int dc5();
}
//创建适配器,将原规范转换为新规范
public class Adapter extends Vc220 implements IDc5{
    private Vc220 vc220;
    public Adapter() {}
    public void setVc220(Vc220 vc220) {
        this.vc220 = vc220;
    }
    @Override
    public int dc5() {
        System.out.println("适配器开始执行:" + vc220.vc());
        int dc5 = vc220.vc() / 44;
        System.out.println("适配器转换结束:" + dc5);
        return dc5;
    }
}
//测试
public class Test {
    public static Adapter adapter = new Adapter();
    public static void main(String[] args) {
        adapter.setVc220(new Vc220());
        adapter.dc5();
    }
}
适配器模式UML

组合模式

桥梁模式

外观模式

享元模式

行为型模式

委派模式(不属于23中设计模式)

基本作用就是负责任务的调度和分配任务,注重结果

  • 精简程序逻辑,提高代码可读性
  • 消除程序中大量的if…else和switch语句
  • 提高算法的保密性和安全性

根据一个调度类,分发请求

//创建员工接口
public interface IEmployee {
    public void doing(String command);
}
//创建员工A,B,C......
public class EmployeeA implements IEmployee{
    public void doing(String command){
        System.out.println("精通 算法 。。。,安排工作:" + command);
    }
}
//创建leader,根据不同的命令判断进行任务调度
public class Leader implements IEmployee{
    @Override
    public void doing(String command) {
        if(command.equals("算法")){
            new EmployeeA().doing(command);
        }else if(command.equals("架构")){
            new EmployeeB().doing(command);
        }
    }
}
//创建老板
public class Boos {
    public void command(String command, Leader leader){
        leader.doing(command);
    }
}
//测试,创建老板实例,发布命令给leader进行执行,leader进行任务调度
public class Test {
    public static void main(String[] args) {
        new Boos().command("算法", new Leader());
    }
}
委派模式UML

策略模式

作用

  • 避免多重分支语句

应用场景

  • 假如系统有很多类,他们的区别仅在于行为不同

  • 一个系统需要动态的在几种算法中选择一种

优点

  • 符合开闭原则
  • 避免过多的条件语句
  • 提高算法的保密性和安全性

缺点

  • 客户端必须知道所有的策略,并自行决定使用哪种策略
  • 代码中会产生非常多的策略类,增加维护难度
//创建抽象接口,
public interface IOperation {
    int operation(int a, int b);
}
//创建实体类,实现接口方法
public class Add implements IOperation {
    @Override
    public int operation(int a, int b) {
        return a + b;
    }
}
//创建实体类,实现接口方法
public class Sub implements IOperation {
    @Override
    public int operation(int a, int b) {
        return a - b;
    }
}
//创建策略类
public class Context implements IOperation{
    private IOperation iOperation;
    public Context() {
    }
    public void setIOperation(IOperation iOperation) {
        this.iOperation = iOperation;
    }
    @Override
    public int operation(int a, int b) {
        return iOperation.operation(a, b);
    }
}
//根据传入的接口,改变Context执行策略
public class Test {
    private static Context context = new Context();
    public static void main(String[] args) {
        context.setIOperation(new Add());
        System.out.println(context.operation(1, 3));
        context.setIOperation(new Sub());
        System.out.println(context.operation(1, 3));
    }
}
委派模式UML

命令模式

模板方法模式

  • 一次性实现算法不变的部分,可变的部分交给子类来实现
  • 各子类公共的部分抽取出来放到父类,避免代码重复
// 构建抽象类
public abstract class AbstractClass {
    //定义执行顺序
    public void templateMethod(){
        this.method1();
      	//钩子方法,根据值判断是否执行下列方法
        if(isCheck()){
            this.method2();
        }
    }
  	//定义不可重写方法
    final void method1(){
        System.out.println("方法1执行");
    }
  	//定义抽象方法,必须重写
    public abstract void method2();
  	//定义方法,可重写
    public boolean isCheck(){
        return false;
    }
}
//创建抽象类实现
public class ConcreteAbstract extends AbstractClass {
  	//可重写方法
    @Override
    public boolean isCheck() {
        return false; //通过改变返回值,决定是否执行重写的钩子方法
    }
    //必须重写的方法
    @Override
    public void method2() {
        System.out.println("执行方法2");
    }
}
//测试
public class Test {
    private static ConcreteAbstract concreteAbstract = new ConcreteAbstract();
    public static void main(String[] args) {
        concreteAbstract.templateMethod();
    }
}
模板方法模式UML

责任链模式

//定义执行器抽象类
public abstract class Handler {
		//下一个执行器
    private Handler nextHandler;
    public Handler getNextHandler() {
        return nextHandler;
    }
    public void setNextHandler(Handler nextHandler) {
        this.nextHandler = nextHandler;
    }
		//执行器执行的方法
    public abstract int handler(int count);
}
//定义具体执行器
public class ConcreteHandler extends Handler{
    @Override
    public int handler(int count) {
      	//业务代码具体操作
        System.out.println("执行器0------------------");
      	//如果下一个执行器存在,则执行
        if(null != getNextHandler()){
            return getNextHandler().handler(count);
        }
        return count;
    }
}
//测试
public class Test {
    public static void main(String[] args) {
        Handler handler = new ConcreteHandler();
        handler.setNextHandler(new ConcreteHandler1());  //定义的第二个具体执行器,可以一直加
        System.out.println(handler.handler(10));
    }
}
责任链模式UML

迭代器模式

中介者模式

观察者模式

又叫发布订阅模式

备忘录模式

访问者模式

状态模式

解释器模式

模式实际应用场景练习

工厂-单例-委派-策略

//创建抽象接口,
public interface IOperation {
    int operation(int a, int b);
}
//创建实体类,实现接口方法
public class Add implements IOperation {
    @Override
    public int operation(int a, int b) {
        return a + b;
    }
}
//创建实体类,实现接口方法
public class Sub implements IOperation {
    @Override
    public int operation(int a, int b) {
        return a - b;
    }
}
//创建策略类
public class Context implements IOperation{
    private IOperation iOperation;
    public Context() {
    }
    public void setIOperation(IOperation iOperation) {
        this.iOperation = iOperation;
    }
    @Override
    public int operation(int a, int b) {
        return iOperation.operation(a, b);
    }
}
//创建工厂方法
public class Factory {
    //私有化工厂
    private Factory() { }
    //注册式单例
    private static final Map<String, IOperation> MAP = new HashMap<>();
    //饿汉-静态代码块初始化
    static {
        MAP.put(constant.ADD, new Add());
        MAP.put(constant.SUB, new Sub());
    }
    //构建工厂类
    //委派模式(注册式单例,通过key进行委派)
    //key尽可能使用枚举类型,防止出问题
    public static IOperation getIOperation(String key){
        if(key.isEmpty()) key = constant.DEFAULT;
        return MAP.get(key);
    }
    //常量
    class constant{
        static final String ADD = "ADD";
        static final String SUB = "SUB";
        static final String DEFAULT = ADD;
    }
}
//测试
public class Test {
    private static Context context = new Context();
    public static void main(String[] args) {
        String key = Factory.constant.SUB;
        context.setIOperation(Factory.getIOperation(key));
        System.out.println(context.operation(1, 3));
    }
}
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值