1. 设计模式
1.1 什么是设计模式
1.2 单例设计模式
package com.itheima.a_单例_饿汉式;
public class T1 {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
Demo demo = Demo.createDemo();
System.out.println(Thread.currentThread() + "::" + demo);
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
Demo demo1 = Demo.createDemo();
System.out.println(Thread.currentThread() + "::" + demo1);
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
Demo demo1 = Demo.createDemo();
System.out.println(Thread.currentThread() + "::" + demo1);
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
Demo demo1 = Demo.createDemo();
System.out.println(Thread.currentThread() + "::" + demo1);
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
Demo demo1 = Demo.createDemo();
System.out.println(Thread.currentThread() + "::" + demo1);
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
Demo demo1 = Demo.createDemo();
System.out.println(Thread.currentThread() + "::" + demo1);
}
}).start();
}
}
class Demo {
private static final Demo demo = new Demo();
public static final Demo createDemo() {
return demo;
}
private Demo() {
}
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
1.3 懒汉式单例设计模式
package com.itheima.b_单例_懒汉式;
/*
单例设计模式
作用:确保一个类只有一个对象。
场景:计算机中的回收站、任务管理器、Java中的Runtime类等
懒汉式(第一次获取时创建对象)
把类的构造器私有(保证别人不能new)
在类中定义一个类变量用于存储对象(注意:此时只定义,不创建)
提供一个类方法,在方法中创建并返回对象(要保证只创建一次)
注意
获取方法需要使用synchronized修饰,以保证只有一个线程可以成功创建出对象
*/
public class Demo {
//在类中定义一个类变量用于存储对象(注意:此时只定义,不创建)
private static volatile Demo demo;
//提供一个类方法,在方法中创建并返回对象(要保证只创建一次)
public static Demo createDemo() {
if (demo == null) {
synchronized (Demo.class) {
if (demo == null) {
demo = new Demo();
}
}
}
return demo;
}
//把类的构造器私有(保证别人不能new)
private Demo() {
}
}
package com.itheima.b_单例_懒汉式;
public class T1 {
public static void main(String[] args) {
while (true) {
new Thread(new Runnable() {
@Override
public void run() {
Demo demo = Demo.createDemo();
System.out.println(Thread.currentThread() + "::" + demo);
}
}).start();
}
}
}
1.4 枚举实现单例模式
package com.itheima.c_单例_枚举实现;
import java.sql.SQLOutput;
/*
单例设计模式
作用:确保一个类只有一个对象。
场景:计算机中的回收站、任务管理器、Java中的Runtime类等
枚举实现单例
直接在枚举中提供一个枚举项就可以实现单例
注意
Google首席Java架构师、(Effective Java》 一书作者Java集合框架的开创者Joshua Bloch在Effective Java一书中提到
单元素的枚举类型,已经成为实现singleton的最佳方法
在这种实现方式中,既可以避免多线程同步问题
还可以防止通过反射和反序列化来重新创建新的对象
在很多优秀的开源代码中,我们经常可以看到使用枚举方式来实现的单例模式类
*/
public class Demo {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Animal.SunQing.hashCode());
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Animal.SunQing.hashCode());
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Animal.SunQing.hashCode());
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Animal.SunQing.hashCode());
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Animal.SunQing.hashCode());
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Animal.SunQing.hashCode());
}
}).start();
}
}
enum Animal{
SunQing
}
2. 动态代理
2.1 入门案例
ProxyUtil.java
package com.itheima.d_动态代理_入门;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 代理工具类,生成代理对象
*/
public class ProxyUtil {
/**
* 创建zxr代理对象
*
* @return
*/
public static Star returnObject(Star item) {
//获取被代理类对象//参数传入
//编写代理类业务逻辑
InvocationHandler handler = new InvocationHandler() {
/**
* @param proxy 生成的代理对象
* @param method 调用代理对象的方法名字
* @param args 参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
if (methodName.equals("sing")) {
// 执行method唱歌
System.out.println("经纪人准备话筒,收钱");
Object obj = method.invoke(item, args);
return obj;
} else {
// 执行method跳舞
System.out.println("经纪人准备场地,收钱");
Object obj = method.invoke(item, args);
return obj;
}
}
};
//生成代理类对象
Object obj = Proxy.newProxyInstance(
item.getClass().getClassLoader(),
item.getClass().getInterfaces(),
handler
);
//返回代理类对象
return (Star) obj;
}
}
Star.interface
package com.itheima.d_动态代理_入门;
//明星接口
public interface Star {
String sing(String name);
/**
* 跳舞
*/
void dancing();
}
ZXR.java
package com.itheima.d_动态代理_入门;
//Sakream实现类
public class ZXR implements Star {
@Override
public String sing(String name) {
System.out.println("zxr开始唱歌,歌名:" + name);
return name;
}
@Override
public void dancing() {
System.out.println("zxr开始跳舞");
}
}
Test.java
package com.itheima.d_动态代理_入门;
public class Test {
public static void main(String[] args) {
// 创建被代理对象
ZXR zxr = new ZXR();
// 创建代理对象
Star star = ProxyUtil.returnObject(zxr);
// 调用代理对象干活
star.sing("罗生门");
star.dancing();
}
}
2.2 业务案例
UserService.interface
package com.itheima.e_动态代理_案例;
/**
* 用户业务接口
*/
public interface UserService {
// 登录功能
void login(String loginName, String passWord) throws Exception;
// 删除用户
void deleteUsers() throws Exception;
// 查询用户,返回数组的形式。
String[] selectUsers() throws Exception;
}
UserServiceImpl.java
package com.itheima.e_动态代理_案例;
/**
* 用户业务实现类
*/
public class UserServiceImpl implements UserService {
@Override
public void login(String loginName, String passWord) throws Exception {
if ("admin".equals(loginName) && "123456".equals(passWord)) {
System.out.println("您登录成功,欢迎光临本系统~");
} else {
System.out.println("您登录失败,用户名或密码错误~");
}
Thread.sleep(1000);
}
@Override
public void deleteUsers() throws Exception {
System.out.println("成功删除了1万个用户~");
Thread.sleep(1500);
}
@Override
public String[] selectUsers() throws Exception {
System.out.println("查询出了3个用户");
String[] names = {"张全蛋", "李二狗", "牛爱花"};
Thread.sleep(500);
return names;
}
}
ProxyUtils.java
package com.itheima.e_动态代理_案例;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.Date;
public class ProxyUtils {
public static UserService createProxy(UserService impl) {
InvocationHandler invocationHandler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 调用代理对象的名字
String methodName = method.getName();
// 计时
long begin = System.currentTimeMillis();
// 执行方法
if (methodName.equals("login")) {
// 记录用户登录日志
System.out.println(new Date() + "--" + Arrays.toString(args) + "用户登录了");
}
Object obj = method.invoke(impl, args);
// 结束
long end = System.currentTimeMillis();
long longTime = end - begin;
System.out.println(methodName + "方法执行了:[" + longTime + "毫秒]");
return obj;
}
};
UserService us = (UserService) Proxy.newProxyInstance(
impl.getClass().getClassLoader(),
impl.getClass().getInterfaces(),
invocationHandler
);
return us;
}
}
Test.java
package com.itheima.e_动态代理_案例;
import java.util.Arrays;
/**
* 目标:使用动态代理解决实际问题,并掌握使用代理的好处。
*/
public class Test {
public static void main(String[] args) throws Exception {
// 1、创建用户业务对象
UserService userService = new UserServiceImpl();
UserService proxy = ProxyUtils.createProxy(userService);
proxy.login("admin", "123456");
proxy.deleteUsers();
String[] names = proxy.selectUsers();
System.out.println("查询到的用户是:" + Arrays.toString(names));
System.out.println("----------------------------------");
}
}