以NFC举例,代码不具备实操功能
接口:INFCService.java
boolean isSupportNFC();
boolean isOpen();
void openNFC(Context context);
void closeNFC(Context context);
//通信交流
void communication();
}
具体实现类:NfcDao.java
public class NfcDao implements INFCService {
private static volatile NfcDao instance;
private static NfcAdapter nfcAdapter;
public NfcDao(Context context) {
nfcAdapter = NfcAdapter.getDefaultAdapter(context);
}
public static NfcDao getInstance(Context context) {
// 双重检查锁定模式 Proxy.newProxyInstance()
if (instance == null) {
synchronized (NfcDao.class) {
if (instance == null) {
instance = new NfcDao(context);
}
}
}
return instance;
}
@Override
public boolean isSupportNFC() {
if (nfcAdapter != null) {
return true;
}
return false;
}
@Override
public boolean isOpen() {
if (nfcAdapter != null){
return nfcAdapter.isEnabled();
}
return false;
}
@Override
public void openNFC(Context context) {
if (nfcAdapter != null && !nfcAdapter.isEnabled()) {
// 创建一个意图以打开 NFC 设置屏幕
Intent intent = new Intent(Settings.ACTION_NFC_SETTINGS);
// 启动活动以打开 NFC 设置屏幕
context.startActivity(intent);
}
}
@Override
public void closeNFC(Context context) {
// 关闭 NFC
try {
Settings.Global.putInt(context.getContentResolver(), Settings.Global.RADIO_NFC, 0);
} catch (Exception e) {
e.printStackTrace();
}
// 请求关闭 NFC 的系统设置
Intent intent = new Intent(Settings.ACTION_NFC_SETTINGS);
context.startActivity(intent);
}
@Override
public void communication() {
}
}
- 静态代理
public class NFCProxy implements INFCService {
private INFCService iNfcService;
public NFCProxy(INFCService iNfcService) {
this.iNfcService = iNfcService;
}
@Override
public boolean isSupportNFC() {
return iNfcService.isSupportNFC();
}
@Override
public boolean isOpen() {
return iNfcService.isOpen();
}
@Override
public void openNFC(Context context) {
iNfcService.openNFC(context);
}
@Override
public void closeNFC(Context context) {
iNfcService.closeNFC(context);
}
@Override
public void communication() {
iNfcService.communication();
}
}
- 动态代理
public class NFCDynamicProxy<T> {
private T target;
public NFCDynamicProxy(T target) {
this.target = target;
}
//只能用于无参构造
public NFCDynamicProxy(Class<T> target) {
try {
this.target = target.newInstance();
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
}
}
/*实验性代码,反射中的有参构造不要android中使用
/,其参数类型无法精准获取抽象类只能获取其实现类类型
,在传入Context后其类型可能是Application或Activity
结果:失败,Type没发强制转换,构造参数类型没发动态获取,此处仅作保留*/
public NFCDynamicProxy(Class<T> target, Object... params) {
Constructor<?>[] constructors = target.getConstructors();
//target.getConstructor(new Class[tClass])
try {
Class<?>[] clzTypeParams = new Class[params.length];
for (int i = 0; i < params.length; i++) {
clzTypeParams[i] = params[i].getClass();
//实验性代码
Type type = params[i].getClass().getGenericSuperclass();
Class<T> tClass = (Class<T>) type;
LogUtil.d("超类名:"+tClass.getName());
}
Constructor<T> constructor = target.getDeclaredConstructor(clzTypeParams);
this.target = constructor.newInstance(params);
}catch (Exception e){
LogUtil.e(e.getMessage());
}
}
public T getProxyInstance() {
T iNfc = (T) Proxy.newProxyInstance(
target.getClass().getClassLoader(), //ClassLoader 类加载器
target.getClass().getInterfaces(), //代理对象接口(必须是接口)
new NfcClientInvocationHandler<T>(target));
return iNfc;
}
}
NfcClientInvocationHandler.java
public class NfcClientInvocationHandler<T> implements InvocationHandler {
private T t;
public NfcClientInvocationHandler(T t) {
this.t = t;
}
//被代理的对象
@Override
public T invoke(Object proxy, Method method, Object[] args) throws Throwable {
LogUtil.i("代理执行方法:" + method.getName() + "=>");
if (args != null && BuildConfig.DEBUG) {
for (int i = 0; i < args.length; i++) {
LogUtil.i("参数为:" + args.toString());
}
}
if (method.getDeclaringClass() == t.getClass()) {
return (T) method.invoke(this, args);
}else {
return (T) method.invoke(t, args);
}
}
}
代理模式好处:给对象套一层壳,便于AOP操作;将操作与调用分离,可以在执行过程中灵活的切换操作对象而不需要改调用者
- 优点
灵活性: 使用代理模式可以轻松地在运行时添加或修改目标对象的行为。
解耦: 代理模式可以降低目标对象和客户端之间的耦合度。
代码复用: 可以在不修改目标对象的情况下,为其添加额外的功能。 - 缺点
性能开销: 由于所有的方法调用都需要通过代理对象进行,可能会导致一定的性能开销。
复杂性: 使用代理模式可能会增加代码的复杂性,特别是当涉及到多个代理时 - 场景,添加日志记录、事务管理,给模块之前的调用进行解耦
动态代理与静态代理的优劣:
- 静态代理:
类的代码在运行前就已经存在,在动态代理中,代理对象是在运行时动态生成的。Java 的 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口提供了这种能力的基础。
优点
性能稍微好一些,因为没有运行时的动态类加载和代理对象创建。
代码更简单,易于理解和维护。
缺点
不够灵活,如果需要为多个类添加相似的功能,会导致代码重复。
违反了开放/封闭原则,每次需要修改目标对象的行为时,都需要修改代理类的代码。- 动态代理
在动态代理中,代理对象是在运行时动态生成的。Java 的 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口提供了这种能力的基础。
优点
高度灵活,可以动态地为任何目标对象添加或修改功能。
更符合开放/封闭原则,可以在不修改目标对象代码的情况下,通过添加新的代理处理器来修改目标对象的行为。
缺点
性能可能稍差,因为所有的方法调用都需要通过代理对象进行,这增加了一层间接性。
代码可能更复杂,需要更多的理解和维护