设计模式

单例模式

1 单例模式 只允许创建一个对象,因此节省内存,加快对象访问速度,因此对象需要被公用的场合适合使用,如多个模块使用同一个数据源连接对象等等
2 单例的缺点 就是不适用于变化的对象,如果同一类型的对象总是要在不同的用例场景发生变化,单例就会引起数据的错误,不能保存彼此的状态。
用单例模式,就是在适用其优点的状态下使用

单例模式是非常常见的模式,因为是单例的所以不存在耦合问题,例如Struts2使用的就是单例模式

单例模式的含义:
通过单例模式可以保证系统中该模式的这个类永远只有一个实例,即一个类永远只有一个对象实例
单例是为了节约内存;
实现单例模式的方式

饿汉单例设计模式:

在类获取对象时,对象已经提前创建好;
设计步骤:
a、私有化构造器
b、定义一个静态变量存储一个对象并赋值
c、提供获取该类的方法

public class Singleton01 {
    //定义一个静态变量存储一个对象
    private static final Singleton01 INSTANCE = new Singleton01();
    //私有化构造器
    private Singleton01(){}

    //提供返回该对象的方法
    public static Singleton01 getInstance(){
        return INSTANCE;
    }

}

懒汉单例设计模式:

真正需要改对象时再去创建这个对象;
设计步骤
a、私有化构造器
b、定义一个静态变量存储一个对象不赋值;
c、提供获取该类的方法

public class Singleton02 {
    //定义一个静态变量存储一个对象
    private static Singleton02 instance02;
    //私有化构造器
    private Singleton02(){}

    //提供返回该对象的方法
    public static Singleton02 getInstance02(){
        if (instance02 == null){
            instance02 = new Singleton02();
        }
        return instance02;
    }
}

动态代理

动态代理简单来说是:拦截对真实对象方法的直接访问,增强真实对象方法的功能

代理类:

java.lang.reflect.Proxy;

具体创建并返回代理对象的方法:

public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)

  • 参数一:类加载器,负责加载做好的代理对象返回!!
  • 参数二:获取当前被代理对象实现的全部接口,以便知道有哪些功能需要被代理起来。方法
  • 参数三:代理的核心处理功能。

动态代理非常的灵活,可以为任意接口和接口实现类对象做代理,
动态代理可以为被代理对象的所有接口的所有方法做代理,动态代理可以在不改变方法源码的情况下,实现对方法功能的增强
动态代理类的字节码在程序运行时右Java发射机制动态生成,无需程序员手工编写他的源代码。
动态代理不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java反射机制可以生成任意类型的动态代理。
动态代理同时也提高了开发效率
缺点,只能针对接口或者接口的实现类做代理对象,普通类是不能做代理对象的。

动态代理工具类:

jdk动态代理:

    public static <T> T getProxy(Object obj){
        /**
         * 参数一:类加载器,负责加载做好的代理对象返回!!
         * 参数二:获取当前被代理对象实现的全部接口,以便知道有哪些功能需要被代理起来。方法
         * 参数三:代理的核心处理功能。
         */
        return (T) Proxy.newProxyInstance(obj.getClass().getClassLoader(),
                obj.getClass().getInterfaces(), new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        // proxy :当前代理对象,我们不会用到。
                        // method:当前业务对象正在执行的方法,就是需要被代理的方法。
                        // args:当前业务对象正在执行方法的入参,就是需要被代理的方法的参数!
                        long startTimer = System.currentTimeMillis();
                        // 真正通知该方法执行。
                        Object rs = method.invoke(obj,args);

                        long endTimer = System.currentTimeMillis();
                        System.out.println(method.getName()+"方法耗时:"+(endTimer - startTimer)/1000.0 + "s"));

                        // 返回方法执行的结果!!
                        return rs;
                    }
            });
    }

cglib动态代理:

导入依赖:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.0.2.RELEASE</version>
</dependency>

官方API:

public static Object create(
    					// 1. 代理对象需要继承的类
                        java.lang.Class superclass,
						// 2. 代理对象需要实现的接口
                        java.lang.Class[] interfaces,
						// 3. 代理对象方法调用时的处理器 InvocationHandler
                        Callback[] callbacks
)

工具类:


    public static <T> T getProxy(final Object obj){
        /**
         * 参数一:/需要继承的实现类!
         * 参数二:代理类需要实现的接口数组 (可传)
         * 参数三:代理对象方法调用的处理器。
         */
        return (T) Enhancer.create(obj.getClass(),
                new Class[]{/*obj.getClass().getInterfaces() */}, new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        // proxy :当前代理对象,我们不会用到。
                        // method:当前业务对象正在执行的方法,就是需要被代理的方法。
                        // args:当前业务对象正在执行方法的入参,就是需要被代理的方法的参数!
                        long startTimer = System.currentTimeMillis();
                        // 真正通知该方法执行。
                        Object rs = method.invoke(obj,args);

                        long endTimer = System.currentTimeMillis();
                        System.out.println(method.getName()+"方法耗时:"+(endTimer - startTimer)/1000.0 +"s");

                        // 返回方法执行的结果!!
                        return rs;
                    }
                });
    }
两种动态代理的区别
JDKCGLIB
实现方式利用 实现 接口方法来拦截目标方法利用 继承 覆写方法来拦截目标方法
性能高低JDK1.6以前较Cglib慢; 1.6以及1.7大量调用时较慢1.8时被JDK代理超越
适用场景目标对象必须实现接口目标方法需要允许覆写(不能用final/static)

装饰模式(静态代理):

装饰模式就是指在不改变原类,动态地扩展一个类的功能

思想

  • 创意一个新类,包装原始类,从而在新类中提升原来类的功能

例子:
BufferedInputStream,BufferedOutputStream,BufferedReader,BufferedWriter等使用的都是装饰模式;
包装类

public class BufferedInputStrem extends InputStream {
    private InputStream is ;
    public BufferedInputStrem(InputStream is){
        this.is = is;
    }
    @Override
    public void read() {
        System.out.println("方法增强~");
        is.read();
    }

    @Override
    public void close() {
        is.close();
    }
}
public class Demo {
    public static void main(String[] args) {
        InputStream is = new BufferedInputStrem(new FileInputStream());
        is.read();
        is.close();
    }
}

工厂模式:

Java中常见的设计模式,他提供了一种新的创建对象的方式——对象由工厂创建,不再需要new对象

作用
对象通过工厂的方法创建返回,工厂的方法可以为该对象进行加工和数据注入
可以实现类与类之间的解耦(核心思想)

例子
spring的IOC使用的就是工厂模式,spring中的ApplicationContext.xml实际上就是一个容器(也就是工厂)

public class FactoryPattern {
    public static Animal getAnimal() {
        Class c = Cat.class;
        Animal animal = null;
        try {
            Constructor constructor = c.getDeclaredConstructor();
            animal = (Animal) constructor.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return animal;
    }
}
public class FactoryDemo {
    public static void main(String[] args) {
        Animal animal = FactoryPattern.getAnimal();
        animal.run();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值