day14-单例设计模式动态代理

devtools/2024/11/13 9:02:47/

一、单例设计模式

单例设计模式作用:确保一个类只有一个对象。场景:计算机中的回收站、任务管理器、Java中的Runtime类等好处:在这些业务场景下,使用单例模式,可以避免浪费内存。

1.1 饿汉式

饿汉式(提前创建对象)把类的构造器私有(保证别人不能new)在类中自己创建一个对象,并赋值到一个变量定义一个静态方法,返回自己创建的这个对象饿汉式单例的特点:    在获取类的对象时,对象已经创建好了。
​单例设计模式:单线程下是一个对象,多线程下也是一个对象
java">public class Demo {public static void main(String[] args) {//单线程下,只有一个对象
//        User user = User.getUser();
//        System.out.println(Thread.currentThread().getName()+":"+user);
//        User user1 = User.getUser();
//        System.out.println(Thread.currentThread().getName()+":"+user1);
​//多线程下,也是一个对象new Thread(new Runnable() {@Overridepublic void run() {User user = User.getUser();System.out.println(Thread.currentThread().getName()+":"+user);}},"A").start();
​new Thread(() -> {User user = User.getUser();System.out.println(Thread.currentThread().getName()+":"+user);},"B").start();
​}
}
class User{private String name;private Integer age;//2. 创建一个自己的对象private static User user = new User();
​// 1. 私有的构造器private User(){}
​// 3. 定义一个静态方法,返回user对象public static User getUser(){return user;}
​public String getName() {return name;}
​public void setName(String name) {this.name = name;}
​public Integer getAge() {return age;}
​public void setAge(Integer age) {this.age = age;}
}

1.2 懒汉式

懒汉式(第一次获取时创建对象)把类的构造器私有(保证别人不能new)在类中定义一个类变量用于存储对象(注意:此时只定义,不创建)提供一个类方法,在方法中创建并返回对象(要保证只创建一次)
​
注意获取方法需要使用synchronized修饰,以保证只有一个线程可以成功创建出对象
java">public class Demo {public static void main(String[] args) {// 单线程
//        Teacher teacher1 = Teacher.getTeacher();
//        System.out.println(teacher1);
//        Teacher teacher2 = Teacher.getTeacher();
//        System.out.println(teacher2);
​//多线程,不能保证返回的是同一个对象(可以加锁解决该问题)for (int i = 0; i < 100; i++) {new Thread(new Runnable() {@Overridepublic void run() {Teacher teacher1 = Teacher.getTeacher();System.out.println(Thread.currentThread().getName()+":"+teacher1);}}).start();}
//        new Thread(new Runnable() {
//            @Override
//            public void run() {
//                Teacher teacher1 = Teacher.getTeacher();
//                System.out.println(Thread.currentThread().getName()+":"+teacher1);
//            }
//        },"t1").start();
//
//        new Thread(new Runnable(){
//            @Override
//            public void run() {
//                Teacher teacher2 = Teacher.getTeacher();
//                System.out.println(Thread.currentThread().getName()+":"+teacher2);
//            }
//        },"t2").start();
​
​
​}
​
}
class Teacher{private String name;private Integer age;//1. 私有化构造器private Teacher(){}
​//2. 定义一个类变量,用于存储对象private static Teacher teacher;
​//3. 定义一个静态方法,返回当前类的对象//3.1 同步方法public static synchronized Teacher getTeacher(){if(teacher==null){teacher = new Teacher();}return teacher;}
//    //3.2 同步代码块
//    public static Teacher getTeacher(){
//        if (teacher == null) {
//            synchronized (Teacher.class) {
//                if (teacher == null) {
//                    teacher = new Teacher();
//                }
//            }
//        }
//        return teacher;
//    }}

1.3 枚举实现单例

枚举实现单例直接在枚举中提供一个枚举项就可以实现单例
​
注意Google首席Java架构师、(Effective Java》 一书作者Java集合框架的开创者Joshua Bloch在Effective Java一书中提到单元素的枚举类型,已经成为实现singleton的最佳方法在这种实现方式中,既可以避免多线程同步问题还可以防止通过反射和反序列化来重新创建新的对象在很多优秀的开源代码中,我们经常可以看到使用枚举方式来实现的单例模式
java">public class Demo {public static void main(String[] args) {// 单线程
//        School school1 = School.ShunYi;
//        System.out.println(Thread.currentThread().getName()+"-->"+school1);
//        School school2 = School.ShunYi;
//        System.out.println(Thread.currentThread().getName()+"-->"+school2);
​// 多线程new Thread(()->{School school = School.ShunYi;System.out.println(Thread.currentThread().getName()+":"+school);},"A").start();
​new Thread(()->{School school = School.ShunYi;System.out.println(Thread.currentThread().getName()+":"+school);},"B").start();}
}
enum School{ShunYi
}

二、动态代理

java">/*** ClassName:Star* Description:*  明星接口*      唱歌*      跳舞*/
public interface Star {// 唱歌public String sing(String name);// 跳舞void dance();
}
/*** ClassName:Yct* Description:*  明星实现类*/
public class Yct implements Star{@Overridepublic String sing(String name) {System.out.println("Yct开始唱歌,歌名" + name);return name;}
​@Overridepublic void dance() {System.out.println("Yct开始跳舞");}
}
/*** ClassName:ProxyUtil* Description:*  创建明星的代理类*/
public class ProxyUtil {//创建明星的代理对象public static Star createProxy(Star star){//1. 获取代理对象对应的类加载器//2. 编写代理类的业务逻辑InvocationHandler invocationHandler = new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//生成的代理对象,代理的方法,代理方法的参数// 1. 获取方法名(调用代理对象的方法名字)String name = method.getName();// 2. 判断是否是唱歌方法if ("sing".equals(name)){// 3. 执行代理方法System.out.println("经纪人-准备话筒-收钱");}else {System.out.println("经纪人-准备场地-收钱");}Object o = method.invoke(star, args);//调用目标对象的方法return o;}};//3. 生成代理对象Object obj = Proxy.newProxyInstance(//用于指定用哪个类加载器,去加载生成的代理类star.getClass().getClassLoader(),//获取当前类加载器,把类加载到JVM中//用于指定代理类需要实现的接口star.getClass().getInterfaces(),//获取当前类实现的接口,代理有哪些行为//用于指定代理类对应的处理器,处理代理类上的方法调用(用来指定生成的代理对象要干什么事情)invocationHandler);//4. 返回代理对象return (Star) obj;}
​
}
/*** ClassName:ProxyUtilTest* Description:*  测试类*/
public class ProxyUtilTest {public static void main(String[] args) {//1. 创建明星对象Yct yct = new Yct();//2. 创建代理对象Star proxy = new ProxyUtil().createProxy(yct);
​//3. 调用代理对象的方法proxy.dance();proxy.sing("小苹果");}
}

使用代理优化用户管理类

场景某系统有一个用户管理类,包含用户登录,删除用户,查询用户等功能,系统要求统计每个功能的执行耗时情况,以便后期观察程序性能。
需求现在,某个初级程序员已经开发好了该模块,请观察该模块的代码,找出目前存在的问题,并对其进行改造。
​
java">/*** 用户业务接口*/
public interface UserService {// 登录功能void login(String loginName, String passWord) throws Exception;
​// 删除用户void deleteUsers() throws Exception;
​// 查询用户,返回数组的形式。String[] selectUsers() throws Exception;
}
​
/*** 用户业务实现类*/
public class UserServiceImpl implements UserService {@Overridepublic void login(String loginName, String passWord) throws Exception {//  long time1 = System.currentTimeMillis();if ("admin".equals(loginName) && "123456".equals(passWord)) {System.out.println("您登录成功,欢迎光临本系统~");} else {System.out.println("您登录失败,用户名或密码错误~");}Thread.sleep(1000);// long time2 = System.currentTimeMillis();// System.out.println("login方法耗时:" + (time2 - time1));}
​@Overridepublic void deleteUsers() throws Exception {//long time1 = System.currentTimeMillis();System.out.println("成功删除了1万个用户~");Thread.sleep(1500);//long time2 = System.currentTimeMillis();//System.out.println("deleteUsers方法耗时:" + (time2 - time1));}
​@Overridepublic String[] selectUsers() throws Exception {//long time1 = System.currentTimeMillis();System.out.println("查询出了3个用户");String[] names = {"张全蛋", "李二狗", "牛爱花"};Thread.sleep(500);//long time2 = System.currentTimeMillis();//System.out.println("selectUsers方法耗时:" + (time2 - time1));return names;}
}
/*** ClassName:UserServiceProxy* Description:*  生成代理对象* @version 1.0* @Author wang* @Creat 2024/9/13 14:52*/
public class UserServiceProxyUtil {public static UserService createProxy(UserService userService){// 1.获取被代理对象----userService
​// 2.创建代理的业务逻辑InvocationHandler invocationHandler = new InvocationHandler(){@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 2.1 获取调用代理对象的方法名String methodName = method.getName();if(methodName.equals("login")){System.out.println( new Date() + "--" + Arrays.toString(args) + "登录了");}// 2.2 进行计时开始long begin = System.currentTimeMillis();
​// 2.3 调用被代理对象的方法Object o = method.invoke(userService, args);
​// 2.4 进行计时结束long end = System.currentTimeMillis();
​// 2.5 计算差值long time = end - begin;System.out.println("方法" + methodName + "耗时:" + time + "毫秒");
​return o;}};// 3.调用Java的API,生成代理对象UserService userService1 = (UserService)Proxy.newProxyInstance(userService.getClass().getClassLoader(), // 类加载器userService.getClass().getInterfaces(),  // 接口invocationHandler);// 4.返回代理对象return userService1;}
}
/*** 目标:使用动态代理解决实际问题,并掌握使用代理的好处。*/
public class Test {public static void main(String[] args) throws Exception{// 1、创建用户业务对象UserService userService = new UserServiceImpl();// 2、创建代理对象UserService userServiceProxy = UserServiceProxyUtil.createProxy(userService);
​// 2、调用用户业务的功能。userServiceProxy.login("admin", "123456");System.out.println("----------------------------------");
​userServiceProxy.deleteUsers();System.out.println("----------------------------------");
​String[] names = userServiceProxy.selectUsers();System.out.println("查询到的用户是:" + Arrays.toString(names));System.out.println("----------------------------------");
​}
}


http://www.ppmy.cn/devtools/114117.html

相关文章

828华为云征文|华为云Flexus X实例docker部署Rocket.Chat构建属于自己的团队通讯协作平台

828华为云征文&#xff5c;华为云Flexus X实例docker部署Rocket.Chat构建属于自己的团队通讯协作平台 华为云最近正在举办828 B2B企业节&#xff0c;Flexus X实例的促销力度非常大&#xff0c;特别适合那些对算力性能有高要求的小伙伴。如果你有自建MySQL、Redis、Nginx等服务…

闲鱼网页版开放,爬虫的难度指数级降低。

爬虫&#xff0c;可以说是程序员最基础的热手项目。 之前我也一直说阿里系的签名系统搞得太复杂&#xff0c;风控太高&#xff0c;很不利于正常的自动化工具开发&#xff0c;这对于需要阿里应用的客户来说&#xff0c;也是一个很难覆盖的成本支出不是。 当然&#xff0c;我做项…

iPhone 16系列:摄影艺术的全新演绎,探索影像新境界

在科技的浪潮中&#xff0c;智能手机摄影功能的进化从未停歇。 苹果公司即将推出的iPhone 16系列&#xff0c;以其卓越的相机升级和创新特性&#xff0c;再次站在了手机摄影的前沿。 从硬件到软件&#xff0c;从拍照体验到图像处理&#xff0c;iPhone 16系列都展现了其在移动…

python毕业设计基于django+vue医院社区医疗挂号预约综合管理系统7918h-pycharm-flask

目录 技术栈和环境说明预期达到的目标具体实现截图系统设计Python技术介绍django框架介绍flask框架介绍解决的思路性能/安全/负载方面可行性分析论证python-flask核心代码部分展示python-django核心代码部分展示操作可行性技术路线感恩大学老师和同学详细视频演示源码获取 技术…

数据结构与算法-18算法专向(hash)

话题引入&#xff1a; 给你N&#xff08;1<N<10&#xff09;个自然数,每个数的范围为&#xff08;1~10000000000&#xff09;。现在让你以最快的速度判断某一个数是否在这N个数内&#xff0c;不得使用已经封装好的类&#xff0c;该如何实现。 A[] new int[N1]&#xff…

k8s1.27.7部署higress,代理非k8s集群业务

一、简介 Higress是基于阿里内部的Envoy Gateway实践沉淀、以开源Istio + Envoy为核心构建的云原生API网关,实现了流量网关 + 微服务网关 + 安全网关三合一的高集成能力,深度集成Dubbo、Nacos、Sentinel等微服务技术栈,能够帮助用户极大的降低网关的部署及运维成本且能力不…

使用llama.cpp 在推理MiniCPM-1.2B模型

llama.cpp 是一个开源项目&#xff0c;它允许用户在C中实现与LLaMA&#xff08;Large Language Model Meta AI&#xff09;模型的交互。LLaMA模型是由Meta Platforms开发的一种大型语言模型&#xff0c;虽然llama.cpp本身并不包含LLaMA模型的训练代码或模型权重&#xff0c;但它…

SQL数据库(MySQL)

一、在Ubuntu系统下安装MySQL数据库 1、更新软件源&#xff0c;在确保ubuntu系统能正常上网的情况下执行以下命令 sudo apt-get update 2、安装MySQL数据库及相关软件包 # 安装过程中设置root用户的密码 123456 sudo apt-get install mysql-server ​ # 安装访问数据库的客…