享元和代理模式

文章目录

享元模式

1.引出享元模式

1.展示网站项目需求
2.传统方案解决
3.问题分析

2.享元模式

1.基本介绍
2.原理类图
3.外部状态和内部状态
4.类图
5.代码实现
1.AbsWebSite.java 抽象的网站
java 复制代码
package com.sun;

/**
 * Description: 抽象的网站
 * @Author sun
 * @Create 2024/6/6 19:45
 * @Version 1.0
 */
public abstract class AbsWebSite {
    public abstract void use(User user);
}
2.ConcreteWebSite.java 具体的网站,type属性是内部状态
java 复制代码
package com.sun;

/**
 * Description: 具体的网站
 * @Author sun
 * @Create 2024/6/6 19:46
 * @Version 1.0
 */
public class ConcreteWebSite extends AbsWebSite {

    // 网站的发布类型
    private String type = "";

    // 在创建网站时把具体的类型传进来
    public ConcreteWebSite(String type) {
        this.type = type;
    }

    @Override
    public void use(User user) {
        System.out.println("网站的发布类型为:" + type + user.getName() + "在使用中");
    }
}
3.WebSiteFactory.java 网站工厂,根据类型,获取对应类型的网站
java 复制代码
package com.sun;

import java.util.HashMap;

/**
 * Description: 网站的工厂类,根据需求,返回一个具体的网站
 * @Author sun
 * @Create 2024/6/6 19:49
 * @Version 1.0
 */
public class WebSiteFactory {

    // 一个集合,充当池的作用
    private HashMap<String, ConcreteWebSite> pool = new HashMap<>();

    public AbsWebSite getWebsiteCategory(String type) {
        // 如果池中没有包含对应类型的对象,就创建一个对象,放到池中
        if (!pool.containsKey(type)) {
            pool.put(type, new ConcreteWebSite(type));
        }
        // 只要到这里了就必然可以拿到对象
        return (AbsWebSite) pool.get(type);
    }

    // 获取池中的网站总数
    public int getWebSiteCount() {
        return pool.size();
    }
}
4.User.java 使用网站的用户,是外部状态
java 复制代码
package com.sun;

/**
 * Description: 享元模式中的外部状态
 * @Author sun
 * @Create 2024/6/6 20:12
 * @Version 1.0
 */
public class User {
    private String name;

    public User(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
5.Client.java
java 复制代码
package com.sun;

/**
 * Description:
 * @Author sun
 * @Create 2024/6/6 20:02
 * @Version 1.0
 */
public class Client {
    public static void main(String[] args) {
        // 创建一个工厂类
        WebSiteFactory webSiteFactory = new WebSiteFactory();
        // 要一个以新闻形式发布的网站
        AbsWebSite webSite = webSiteFactory.getWebsiteCategory("新闻");
        webSite.use(new User("tom"));
        // 要一个以博客形式发布的网站,后面即使要更多相同类型的网站,都会直接从池中获取,而不会创建新的实例
        AbsWebSite webSite2 = webSiteFactory.getWebsiteCategory("博客");
        webSite2.use(new User("jack"));
        AbsWebSite webSite3 = webSiteFactory.getWebsiteCategory("博客");
        webSite3.use(new User("lisa"));
        AbsWebSite webSite4 = webSiteFactory.getWebsiteCategory("博客");
        webSite4.use(new User("milan"));
        int webSiteCount = webSiteFactory.getWebSiteCount();
        System.out.println("webSiteCount = " + webSiteCount);
    }
}
6.结果
6.小结

3.享元模式在Integer的应用

代理模式

1.基本介绍

1.介绍
2.简单类图

2.静态代理

1.基本介绍
2.类图
3.代码实现
1.目录结构
2.ITeacherDao.java 被代理的接口
java 复制代码
package com.sun.staticproxy;

/**
 * Description: 接口
 * @Author sun
 * @Create 2024/6/7 19:05
 * @Version 1.0
 */
public interface ITeacherDao {
    void teach();
}
3.TeacherDao.java 被代理的实现类
java 复制代码
package com.sun.staticproxy;

/**TeacherDaoProxy.java
 * Description: 实现类
 * @Author sun
 * @Create 2024/6/7 19:06
 * @Version 1.0
 */
public class TeacherDao implements ITeacherDao{
    @Override
    public void teach() {
        System.out.println("老师正在授课中");
    }
}
4.TeacherDaoProxy.java 静态代理类
java 复制代码
package com.sun.staticproxy;

/**
 * Description: 代理TeacherDao
 * @Author sun
 * @Create 2024/6/7 19:06
 * @Version 1.0
 */
public class TeacherDaoProxy implements ITeacherDao{

    // 使用构造器进行聚合
    private ITeacherDao teacherDao;

    public TeacherDaoProxy(ITeacherDao teacherDao) {
        this.teacherDao = teacherDao;
    }

    @Override
    public void teach() {
        System.out.println("代理开始");
        teacherDao.teach();
        System.out.println("代理结束");
    }
}
5.Client.java
java 复制代码
package com.sun.staticproxy;

/**
 * Description:
 * @Author sun
 * @Create 2024/6/7 19:11
 * @Version 1.0
 */
public class Client {
    public static void main(String[] args) {
        TeacherDaoProxy teacherDaoProxy = new TeacherDaoProxy(new TeacherDao());
        teacherDaoProxy.teach();
    }
}
6.结果

2.动态代理(JDK代理)

1.基本介绍
2.类图
3.代码实现
1.ITeacherDao.java 被代理的接口
java 复制代码
package com.sun.dynamic;

/**
 * Description: 被代理的接口
 * @Author sun
 * @Create 2024/6/7 19:25
 * @Version 1.0
 */
public interface ITeacherDao {

    void teach(String name);

}
2.TeacherDao.java 被代理的类
java 复制代码
package com.sun.dynamic;

/**
 * Description: 实现类
 * @Author sun
 * @Create 2024/6/7 19:06
 * @Version 1.0
 */
public class TeacherDao implements ITeacherDao {

    @Override
    public void teach(String name) {
        System.out.println(name + "老师正在授课中");
    }

}
3.ProxyFactory.java 代理工厂,返回动态代理对象
java 复制代码
package com.sun.dynamic;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;

/**
 * Description: 动态代理对象,可以对其代理的对象的任意方法添加任意操作
 * @Author sun
 * @Create 2024/6/7 19:27
 * @Version 1.0
 */
public class ProxyFactory {

    // 构造器聚合一个目标对象
    private Object target;

    public ProxyFactory(Object target) {
        this.target = target;
    }

    // 给目标对象,生成一个代理对象
    public Object getProxyInstance() {
        /**
         * 参数说明:
         * ClassLoader loader:指定当前目标对象使用的类加载器
         * Class<?>[] interfaces:是目标对象实现的接口类型,使用泛型方法确认类型
         * InvocationHandler h:是事件处理,当使用代理对象调用目标对象的方法时会触发
         */
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
            /**
             * method:目标方法的Method对象,可以用来调用目标任何方法
             * args:目标方法的参数,也就是动态代理对象调用目标任何方法时传入的参数
             * @return 返回调用目标方法的返回值,也可以返回null
             * @throws Throwable
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("method = " + method + ", args = " + Arrays.toString(args));
                System.out.println("动态代理开始");
                /*
                invoke方法的第一个参数是目标对象,第二个参数的目标方法的参数
                 */
                Object result = method.invoke(target, args);
                System.out.println("动态代理结束");
                return result;
            }
        });
    }
}
4.Client.java
java 复制代码
package com.sun.dynamic;

/**
 * Description:
 * @Author sun
 * @Create 2024/6/7 19:47
 * @Version 1.0
 */
public class Client {
    public static void main(String[] args) {
        // 创建一个目标对象
        ITeacherDao target = new TeacherDao();
        // 得到代理对象
        ITeacherDao proxy = (ITeacherDao) new ProxyFactory(target).getProxyInstance();
        // 使用代理对象调用方法
        proxy.teach("李华");
    }
}
5.结果

3.Cglib代理

1.基本介绍
2.注意事项
3.类图
4.引入四个jar包
5.代码实现
1.目录结构
2.TeacherDao.java 被代理的类
java 复制代码
package com.sun.cglib;

/**
 * Description: 被代理的类
 * @Author sun
 * @Create 2024/6/8 19:37
 * @Version 1.0
 */
public class TeacherDao {

    public void teach(String name) {
        System.out.println(name + "老师授课中,使用的是cglib代理,不需要实现接口");
    }
}
3.ProxyFactory.java 返回代理对象的工厂
java 复制代码
package com.sun.cglib;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * Description:
 * @Author sun
 * @Create 2024/6/8 19:38
 * @Version 1.0
 */
public class ProxyFactory implements MethodInterceptor {

    // 构造器聚合一个目标对象
    private Object target;

    public ProxyFactory(Object target) {
        this.target = target;
    }

    // 返回目标对象的代理对象
    public Object getProxyInstance() {
        //1.创建一个工具类
        Enhancer enhancer = new Enhancer();
        //2.设置父类
        enhancer.setSuperclass(target.getClass());
        //3.设置回调函数
        enhancer.setCallback(this);
        //4.创建子类对象
        return enhancer.create();
    }

    /**
     * 当使用代理对象调用目标对象的函数时,就会跳到这个函数,跟之前动态代理时类似
     * @param o
     * @param method 代理对象调用的目标对象的函数
     * @param args 函数的参数
     * @param methodProxy
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("cglib代理模式开始");
        // 调用目标对象的函数
        System.out.println("method = " + method);
        System.out.println("args = " + args);
        Object returnVal = method.invoke(target, args);
        System.out.println("cglib代理结束");

        return returnVal;
    }
}
4.Client.java
java 复制代码
package com.sun.cglib;

/**
 * Description:
 * @Author sun
 * @Create 2024/6/8 19:50
 * @Version 1.0
 */
public class Client {
    public static void main(String[] args) {
        // 创建一个目标对象
        TeacherDao teacherDao = new TeacherDao();
        // 得到目标对象的代理对象
        ProxyFactory proxyFactory = new ProxyFactory(teacherDao);
        TeacherDao proxyInstance = (TeacherDao) proxyFactory.getProxyInstance();
        // 使用代理对象来调用目标对象函数,则会被代理
        proxyInstance.teach("小明");
    }
}
5.结果
6.几种变体
相关推荐
StayInLove3 分钟前
G1垃圾回收器日志详解
java·开发语言
无尽的大道11 分钟前
Java字符串深度解析:String的实现、常量池与性能优化
java·开发语言·性能优化
爱吃生蚝的于勒14 分钟前
深入学习指针(5)!!!!!!!!!!!!!!!
c语言·开发语言·数据结构·学习·计算机网络·算法
binishuaio24 分钟前
Java 第11天 (git版本控制器基础用法)
java·开发语言·git
zz.YE26 分钟前
【Java SE】StringBuffer
java·开发语言
就是有点傻30 分钟前
WPF中的依赖属性
开发语言·wpf
洋24038 分钟前
C语言常用标准库函数
c语言·开发语言
进击的六角龙40 分钟前
Python中处理Excel的基本概念(如工作簿、工作表等)
开发语言·python·excel
wrx繁星点点41 分钟前
状态模式(State Pattern)详解
java·开发语言·ui·设计模式·状态模式
NoneCoder1 小时前
Java企业级开发系列(1)
java·开发语言·spring·团队开发·开发