软件开发思考


设计模式分类

GoF提出的设计模式总共有23种

根据目的准则分类,分为三大类

创建型设计模式,共5种:单例模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式。

结构型设计模式,共7种:适配器模式、装饰模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

行为型设计模式,共11种:策略模式、模板方法模式、观察者模式、迭代器模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

另外,随着设计模式的发展也涌现出很多新的设计模式:它们分别是规格模式、对象池模式、雇工模式、黑板模式和空对象模式等。
 


创建型: 

工厂方法类图

/**
 * 工厂方法模式 --- 工厂类通过类方法创建产品
 * 使用场景: 频繁创建对象,后续可能存在修改实例化
 * 目的:可以隐藏创建过程(实例化过程),实例化处与调用方解耦
 * 带来的好处: 后期如果存在实例化改造,只需要在工厂类中处理
 * */
public class GDComputerFactory extends ComputerFactory {
    @Override
    public <T extends Computer> T createComputer(Class<T> clz) {
        Computer computer = null;
        String className = clz.getName();
        try {
            computer = (Computer) Class.forName(className).newInstance();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return (T) computer;
    }
}


public abstract class ComputerFactory {
    public abstract <T extends Computer> T createComputer(Class<T> clz);
}


public abstract class Computer {
    public abstract void start();
}


public class LenovoComputer extends Computer {
    @Override
    public void start() {
        System.out.println("LenovoComputer is out of date.");
    }
}

/**
 * builder 模式
 * 使用场景:
 * 创建对象过于复杂,需要创建独立于对象的组成部分以及它们的装配方式
 * 相同的方法,不同的执行顺序,产生不同的事件结果
 * 多个部件或零件都可以被装配到一个对象中,但是产生的运行结果又不相同时
 * 产品类非常复杂,或者产品类中的调用顺序不同而产生不同的效能
 *
 * 在创建一个复杂的对象时,这些对象的内部组成构件间的建造顺序是稳定的,但是对象的内部组成构件面临着复杂的变化
 * */
public abstract class Builder {
    public abstract void buildCpu(String cpu);

    public abstract void buildMainboard(String mainBoard);

    public abstract void buildRam(String ram);

    public abstract Computer create();
}


public class Director {
    Builder mBuild = null;

    public Director(Builder build) {
        mBuild = build;
    }

    public void setBuild(Builder build) {
        mBuild = build;
    }

    public Computer createComputer(String cpu, String mainboard, String ram) {
        mBuild.buildMainboard(mainboard);
        mBuild.buildCpu(cpu);
        mBuild.buildRam(ram);
        return mBuild.create();
    }
}


public class MoonComputerBuilder extends Builder {
    private Computer mComputer = new Computer();

    @Override
    public void buildCpu(String cpu) {
        mComputer.setmCpu(cpu);
    }

    @Override
    public void buildMainboard(String mainBoard) {
        mComputer.setmMainboard(mainBoard);
    }

    @Override
    public void buildRam(String ram) {
        mComputer.setmRam(ram);
    }

    @Override
    public Computer create() {
        return mComputer;
    }
}

public class Computer {
    private String mCpu;
    private String mMainboard;
    private String mRam;


    public String getmCpu() {
        return mCpu;
    }

    public void setmCpu(String mCpu) {
        this.mCpu = mCpu;
    }

    public String getmMainboard() {
        return mMainboard;
    }

    public void setmMainboard(String mMainboard) {
        this.mMainboard = mMainboard;
    }

    public String getmRam() {
        return mRam;
    }

    public void setmRam(String mRam) {
        this.mRam = mRam;
    }
}



反向编译

JAD Java Decompiler Download Mirrorhttps://varaneckas.com/jad/jad [*.class]

高频

单例

 通过静态类,静态方法实现单例。反射破坏单例

/**
 * 正常调用方法或者 多线程都能反正单例
 * 反射会破坏单例
 */
public class LazyInnerClassSingleton {
    private LazyInnerClassSingleton() {

    }

    // static 为了使单例的空间共享,保证这个方法不会被重写、重载
    // final 当某个类的整体定义为final时,就表明了你不能打算继承该类,而且也不允许别人这么做。即这个类是不能有子类的。
    public static final LazyInnerClassSingleton getInstance() {
        return LazyHolder.instantce;
    }

    private static class LazyHolder {
        private static final LazyInnerClassSingleton instantce = new LazyInnerClassSingleton();
    }
}


import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class LazyInnerClassSingletonTest {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class<?> clazz = LazyInnerClassSingleton.class;
        Constructor c = clazz.getDeclaredConstructor(null);
        c.setAccessible(true);

        Object o1 = c.newInstance();
        Object o2 = c.newInstance();
        Object o3 = LazyInnerClassSingleton.getInstance();
        // new 三次,犯了原则性错误, 无法实现单例
        System.out.println(o1 == o2);
        System.out.println(o2 == o3);
        System.out.println(o3 == o1);
    }
}


采用 Enum  不能反射构造,实例化,static 特性,完美实现单例

/**
*ENUM static 实例化保证对象单例
*反射不能实例化, JDK 对Enum newInstance throw 
*推荐通过 enum 实现单例
**/ 


enum EnumSingleton {
    // static object
    INSTANCE,
    AAAA;

    private Object data; // share in enum

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public static EnumSingleton getInstance() {
        return INSTANCE;
    }
}

static 
{
    INSTANCE = new EnumSingleton("INSTANCE", 0);
    AAAA = new EnumSingleton("AAAA", 1);
    $VALUES = (new EnumSingleton[] {
        INSTANCE, AAAA
    });
}

   @CallerSensitive
    public T newInstance(Object ... initargs)
        throws InstantiationException, IllegalAccessException,
               IllegalArgumentException, InvocationTargetException
    {
        if (!override) {
            if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
                Class<?> caller = Reflection.getCallerClass();
                checkAccess(caller, clazz, null, modifiers);
            }
        }
        // intercept 拦截 Enum 实例化
        if ((clazz.getModifiers() & Modifier.ENUM) != 0)
            throw new IllegalArgumentException("Cannot reflectively create enum objects");
        ConstructorAccessor ca = constructorAccessor;   // read volatile
        if (ca == null) {
            ca = acquireConstructorAccessor();
        }
        @SuppressWarnings("unchecked")
        T inst = (T) ca.newInstance(initargs);
        return inst;
    }

Threadlocal 能够保证在本线程内单例, 反射也会破坏。实现原理,hasmap,key为currentThread


public class testthreadlocal {
    public static class ThreadLocalSingleton {
        private static final ThreadLocal<ThreadLocalSingleton> threadLocalInstance =
                new ThreadLocal() {
                    @Override
                    protected ThreadLocalSingleton initialValue() {
                        return new ThreadLocalSingleton();
                    }
                };

        private ThreadLocalSingleton() {
        }

        public static ThreadLocalSingleton getInstance() {
            return threadLocalInstance.get();
        }
    }

    public static void main(String[] args) {
        System.out.println(ThreadLocalSingleton.getInstance());
        System.out.println(ThreadLocalSingleton.getInstance());
        System.out.println(ThreadLocalSingleton.getInstance());
        System.out.println(ThreadLocalSingleton.getInstance());
        System.out.println(ThreadLocalSingleton.getInstance());
        System.out.println(ThreadLocalSingleton.getInstance());

        Class clazz = ThreadLocalSingleton.class;
        try {
            Constructor c = clazz.getDeclaredConstructor(null);
            c.setAccessible(true);
            try {
                Object o1 = c.newInstance();
                System.out.println("reflect --> " + o1);
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        Thread t1 = new Thread(new ExectorThread());
        Thread t2 = new Thread(new ExectorThread());
        t1.start();
        t2.start();
        System.out.println("End");
    }
}

通过clone方式 实现prototype,优雅地复制对象

/**
 * 原型模式(Prototype Pattern)是指原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。
 * 原型模式主要适用于以下场景:
 * a). 类初始化消耗资源较多。
 * b). 使用 new 生成一个对象需要非常烦琐的过程(数据准备、访问权限等)。
 * c). 构造函数 较复杂。
 * d). 在循环体中产生大量对象。
 * */
package main.prototype;

import java.io.*;
import java.util.Date;

public class QiTianDaSheng extends Monkey implements Cloneable, Serializable {
    public JinGuBang jinGuBang;

    public QiTianDaSheng() {
        this.birthday = new Date();
        this.jinGuBang = new JinGuBang();
    }

    // 我们已经清楚Object.clone()是protected方法。这说明,该方法可以被同包(java.lang)下以及它(java.lang.Object)的子类访问
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return this.deepClone();
    }

    public Object deepClone() {
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(this);


            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bis);

            QiTianDaSheng copy = (QiTianDaSheng) ois.readObject();
            copy.birthday = new Date();
            return copy;
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
            return null;
        }
    }

    public QiTianDaSheng shallowClone(QiTianDaSheng target) {
        QiTianDaSheng copy = new QiTianDaSheng();
        copy.height = target.height;
        copy.weight = target.weight;

        copy.jinGuBang = target.jinGuBang;
        copy.birthday = target.birthday;
        return copy;
    }
}

JDK ProxyGenerator 动态生成代理类.class

step1: 生成代理类class 字节码

        > 保存 className,interfaces,accessFlags

        > 将 hasCode,equals, toString 加入到 proxyMethods (Map<String, List<ProxyMethod>>

        > 将被代理(目标)对象中的Methods加入到proxyMethods

        > 将<init> <proxyMethods> <cinit> 加入到methods(List<MethodInfo>)中

        > 添加常量信息到ConstantPool

                >> className、"java/lang/reflect/Proxy"、interfaces 对应的包路径名

        > 开始写入数据

                >> 先写入4个字节魔鬼数字,用来确定是否能被虚拟机接受的class文件

                >> 次版本号0, 主版本号49

                >> 写入常量ConstantPool   IndirectEntry(tag index0 index1(tag 9(FiledRef) 10(MethodRef) 11(InterfaceMethodRef) 12(NameAndType)))

                >> accessFlags

                >> cp中 className、"java/lang/reflect/Proxy"对应 index

                >> 接口数量、接口对应的cp index

                >> 字段数量、FieldIfno

        >> methods, MethodInfo

                >> 生成代理类 自身属性数量 0

                >> 将   ByteArrayOutputStream 转成 ByteArray

        step2: 通过 Proxy static native Class<?> defineClass0(ClassLoader loader, String name, byte[] b, int off, int len); 加入到jvm中

注意: 

为了保证 生成 class 唯一,使用了 

        // next number to use for generation of unique proxy class names
        private static final AtomicLong nextUniqueNumber = new AtomicLong();

ConstantPool 插入IndirectEntry不重复的关键在于实现了 equals方法
            public boolean equals(Object var1) {
                if (var1 instanceof ConstantPool.IndirectEntry) {
                    ConstantPool.IndirectEntry var2 = (ConstantPool.IndirectEntry) var1;
                    if (this.tag == var2.tag && this.index0 == var2.index0 && this.index1 == var2.index1) {
                        return true;
                    }
                }

                return false;
            }

CGLIB 和JDK 代理 生成class文件区别

 No1. CGLIB 采用 extends,JDK 采用 interfaces

 No2. CGLIB采用 fastClass(index ,c1(代理类), c2(被代理类),  f1, f2) 方式生成class文件,JDK 采用 ProxyGenerator生成class文件

                生效效率: jdk高

                执行效率: cglib高

委派模式 (delegate pattern) 不属于GoF 23中设计模式。

正则表达式:

获取文件后缀 和 获取 文件名

    String regex = "([a-zA-z]+)$"; // 只匹配 符号后面的内容

    String imageName = "E://hello//abc.document";

    Pattern p = Pattern.compile(regex);

    Matcher m = p.matcher(imageName);

    // boolean b = m.matches();

    if (m.find()) {

        System.out.println("1111-> " + m.groupCount() + m.group(1));

     } else {

         System.out.println("not found...");

     }


        String regex = "//([a-zA-z0-9_]+)"; // 获取文件名

        String imageName = "E://hello//abc_123.document";
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(imageName);

        int startIndex = 0;
        while(m.find(startIndex)) {
            for (int i = 0; i < m.groupCount(); i++) {
                System.out.println("============" + startIndex + "============");
                System.out.println((i + 1) + " ======== " + m.group(i + 1));
                System.out.println("========================");
            }
            startIndex = m.end();
        }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值