1. 单例模式
1.1 饿汉式
class HungrySingleton{
private static HungrySingletonTest instance = new HungrySingletonTest();
private HungrySingleton(){}
public static HungrySingletonTest getInstance() {
return instance;
}
}
1.2 懒汉式
class LazySingleton{
private static volatile LazySingleton instance;
private LazySingleton(){}
public static LazySingleton getInstance() {
if (instance == null){
synchronized (LazySingleton.class){
if (instance == null)
instance = new LazySingleton();
}
}
return instance;
}
}
1.3 内部类式
class InnerClassSingleton{
// 此静态内部类只会在第一次调用getInstance()方法时进行加载和初始化
private static class InnerClassHolder{
private static InnerClassSingleton instance = new InnerClassSingleton();
}
private InnerClassSingleton(){
// 防止通过反射获取新实例
if (InnerClassHolder.instance != null){
throw new RuntimeException("单例模式不允许创建多个实例");
}
}
public static InnerClassSingleton getInstance(){
return InnerClassHolder.instance;
}
}
2. 简单工厂
class ProductSimpleFactory{
public static Product getProduct(String type){
if ("ProductA".equals(type)){
return new ProductA();
}else if ("ProductB".equals(type)){
return new ProductB();
}else {
return null;
}
}
}
interface Product{
public void produce();
}
class ProductA implements Product{
@Override
public void produce() {
System.out.println("A产品被生产出来了");
}
}
class ProductB implements Product{
@Override
public void produce() {
System.out.println("B产品被生产出来了");
}
}
3. 工厂方法
// 工厂接口
interface CarFactory{
Car getCar();
}
// 两个工厂类
class BMWFactory implements CarFactory{
@Override
public BMW getCar() {
return new BMW();
}
}
class BenzFactory implements CarFactory{
@Override
public Benz getCar() {
return new Benz();
}
}
interface Car{
void run();
}
class BMW implements Car{
@Override
public void run() {
System.out.println("宝马在路上跑");
}
}
class Benz implements Car{
@Override
public void run() {
System.out.println("奔驰在路上跑");
}
}
4. 静态代理
静态代理: 需要定义接口或者父类, 被代理对象和代理对象一起实现相同的接口或者继承相同父类优点 : 在不修改目标对象的情况下可对对象中的方法进行增强缺点 : 代理对象和被代理对象都需要实现相同接口或继承相同父类, 因此会产生很多代理类, 且一旦接口增加方法, 目标对象和代理对象均需修改
// 代理类和被代理类都需要实现该接口
interface ITeacherDao{
void teach();
}
// 被代理对象
class TeacherDao implements ITeacherDao{
@Override
public void teach() {
System.out.println("被代理对象在teaching");
}
}
// 代理对象
class TeacherDaoProxy implements ITeacherDao{
// 目标对象(被代理对象)
private ITeacherDao target;
// 构造器
public TeacherDaoProxy(ITeacherDao target) {
this.target = target;
}
@Override
public void teach() {
System.out.println("执行代理对象的teach方法");
target.teach();
System.out.println("代理结束");
}
}
5. JDK动态代理
动态代理(JDK) : 代理对象不需要实现接口, 被代理对象需要实现接口
CGlib动态代理 : cglib是第三方工具库, 可以创建代理对象. cglib的原理是继承, cglib通过继承目标类, 创建它的子类, 重写父类的方法, 实现功能的修改
因为cglib是继承, 并重写方法, 因此要求目标类可被继承, 即目标类和目标方法不是final的
由此可见, cglib对目标类的要求比较宽松, 只要能继承即可, 不要求目标类实现某个接口, 因此在框架中大量使用cglib动态代理
public class DynamicProxyTest {
public static void main(String[] args) {
// 1. 创建被代理类
TeacherDao1 teacherDao = new TeacherDao1();
teacherDao.setName("张三");
// 2. 创建代理工程, 传入被代理类
ProxyFactory proxyFactory = new ProxyFactory(teacherDao);
// 3. 从代理工厂中获取代理对象实例, 强转为被代理类
ITeacherDao1 proxyInstance = (ITeacherDao1)proxyFactory.getProxyInstance();
// 4. 通过代理类调用方法
proxyInstance.teach();
}
}
interface ITeacherDao1{
void teach();
}
// 被代理对象
class TeacherDao1 implements ITeacherDao1{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void teach() {
System.out.println("我叫:" + this.name + ", 被代理对象在teaching...");
}
}
class ProxyFactory{
// 维护一个目标对象
private Object target;
// 构造器, 对target进行初始化
public ProxyFactory(Object target) {
this.target = target;
}
public Object getProxyInstance(){
// Proxy.newProxyInstance() 的作用是创建代理对象, 它的的返回值就是目标对象的代理对象
// 参数1:ClassLoader loader : 类加载器, 负责向内存中加载对象, 可以使用反射获取类的类加载器
// 参数2:Class<?>[] interfaces : 目标类实现的接口, 也可以通过反射获取
// 参数3:InvocationHandler h : 这个是有我们编写的, 用于实现代理类需要完成的功能
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("动态代理开始");
Object returnValue = method.invoke(target, args);
System.out.println("动态代理结束");
return returnValue;
}
});
}
}