Java设计模式
目标
- 学习反射技术,掌握反射的基本概念
- 着重学习全书的重点——动态代理和责任链模式,以及拦截器概念
- 掌握观察者模式
- 掌握工厂和抽象工厂模式
- 掌握Builder (构建)模式
学习反射技术,掌握反射的基本概念
Java反射技术应用广泛,它能够配置:类的全限定名,方法和参数,完成对象的初始化,甚至是反设莫些方法
通过反射构建对象
package com.lean.ssm.chapter2.reflect;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ReflectServiceImpl {
public void sayHello(String name) {
System.err.println("Hello " + name);
}
}
反射生成对象
package com.lean.ssm.chapter2.reflect;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ReflectTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
ReflectTest reflectTest = new ReflectTest();
System.out.println(reflectTest.getInstance());
}
public ReflectServiceImpl getInstance() {
ReflectServiceImpl object = null;
try {
object = (ReflectServiceImpl) Class.forName("com.lean.ssm.chapter2.reflect.ReflectServiceImpl")
.newInstance();
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException ex) {
ex.printStackTrace();
}
return object;
}
}
运行代码将实例化,返回结果
com.lean.ssm.chapter2.reflect.ReflectServiceImpl@15db974
更改反射生成对象,使其参数赋值
package com.lean.ssm.chapter2.reflect;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ReflectTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
ReflectTest reflectTest = new ReflectTest();
System.out.println(reflectTest.getInstance());
}
public ReflectServiceImpl getInstance() {
ReflectServiceImpl object = null;
try {
object = (ReflectServiceImpl) Class.forName("com.lean.ssm.chapter2.reflect.ReflectServiceImpl")
.newInstance();
object.sayHello("张武");
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException ex) {
ex.printStackTrace();
}
return object;
}
}
运行代码将实例化,返回结果
Hello 张武
com.lean.ssm.chapter2.reflect.ReflectServiceImpl@15db9742
完整代码
ReflectServiceImpl.java
package com.lean.ssm.chapter2.reflect;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ReflectServiceImpl {
public void sayHello(String name) {
System.err.println("Hello " + name);
}
}
ReflectServiceImpl2.java
package com.lean.ssm.chapter2.reflect;
import java.lang.reflect.InvocationTargetException;
public class ReflectServiceImpl2 {
private String name;
public ReflectServiceImpl2(String name) {
this.name = name;
}
public void sayHello() {
System.err.println("hello " + name);
}
public ReflectServiceImpl2 getInstance() {
ReflectServiceImpl2 object = null;
try {
object =
(ReflectServiceImpl2)
Class.forName("com.lean.ssm.chapter2.reflect.ReflectServiceImpl2").
getConstructor(String.class).newInstance("张三");
} catch (ClassNotFoundException | InstantiationException
| IllegalAccessException | NoSuchMethodException
| SecurityException | IllegalArgumentException
| InvocationTargetException ex) {
ex.printStackTrace();
}
return object;
}
}
ReflectTest.java
ReflectServiceImpl target = new ReflectServiceImpl();
等于object = (ReflectServiceImpl) Class.forName("com.lean.ssm.chapter2.reflect.ReflectServiceImpl")
.newInstance();
package com.lean.ssm.chapter2.reflect;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ReflectTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
ReflectTest reflectTest = new ReflectTest();
System.out.println(reflectTest.getInstance());
// System.err.println(reflectTest.reflectMethod());
// System.out.println(reflectTest.reflect());
}
public ReflectServiceImpl getInstance() {
ReflectServiceImpl object = null;
try {
object = (ReflectServiceImpl) Class.forName("com.lean.ssm.chapter2.reflect.ReflectServiceImpl")
.newInstance();
object.sayHello("张武");
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException ex) {
ex.printStackTrace();
}
return object;
}
public Object reflectMethod() {
Object returnObj = null;
ReflectServiceImpl target = new ReflectServiceImpl();
try {
Method method = ReflectServiceImpl.class.getMethod("sayHello", String.class);
returnObj = method.invoke(target, "张三");
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException
| InvocationTargetException ex) {
ex.printStackTrace();
}
return returnObj;
}
public Object reflect() {
ReflectServiceImpl object = null;
try {
object = (ReflectServiceImpl) Class.forName("com.lean.ssm.chapter2.reflect.ReflectServiceImpl")
.newInstance();
Method method = object.getClass().getMethod("sayHello", String.class);
method.invoke(object, "张三");
} catch (NoSuchMethodException | SecurityException | ClassNotFoundException | IllegalAccessException
| IllegalArgumentException | InvocationTargetException | InstantiationException ex) {
ex.printStackTrace();
}
return object;
}
}
着重学习全书的重点——动态代理和责任链模式,以及拦截器概念
动态代理:动态代理的意义在于生成一个占位(又称代理对象),来代理真是对象,从而控制真实的对象的访问。
代理必须分为两个步骤:
- 代理对象和正式对象建立代理关系
- 实现代理对象的代理逻辑方法
JAVA中有多种代理技术,比如JDK,CGLIB,Javassist,ASM,其中最常用的JDK,CGLIB。
JDK动态代理
JDK动态代理是java.lang.reflect.提供的方式。它必须借助一个接口才能产生代理对象,所以先定义接口。*
package com.lean.ssm.zw.proxy;
public interface HelloWorld {
public void sayHelloWorld();
}
然后实习这些接口
package com.lean.ssm.zw.proxy;
public class HelloWorldImpl implements HelloWorld {
@Override
public void sayHelloWorld() {
// TODO Auto-generated method stub
System.out.println("Hello World");
}
}
实现了最简单的java接口和实现来的关系,下面开始实现动态代理,
先建立代理对象和正式对象建立代理关系,后实现代理对象的代理逻辑方法
在JDK动态代理中,要实现逻辑类必须去实现java.lang.reflect.InvocationHandler接口,它里面定义了一个invoke方法,并提供接口数组用于挂在代理对象。
package com.lean.ssm.zw.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JdkProxyExcample implements InvocationHandler {
private Object target=null;
public Object bind(Object target) {
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
System.out.println("进入代理方法");
System.out.println("在调度真实对象之前的服务");
Object object =method.invoke(target, args);
System.out.println("在调度真实对象之后的服务");
return object;
}
}
package com.lean.ssm.zw.proxy;
public class ProxyText {
public static void main(String[] args) {
// TODO Auto-generated method stub
testJdkProxy1();
}
public static void testJdkProxy1() {
JdkProxyExcample jdk=new JdkProxyExcample();
HelloWorld proxy= (HelloWorld) jdk.JdkProxyExcample(new HelloWorldImpl());
proxy.sayHelloWorld();
}
}
CGLIB第三方动态代理(优点不需要提供接口,只要一个抽象类)(jar 包)(asm.jar,cglib.jar)
ReflectServiceImpl
package com.zw.proxyCGLiB;
public class ReflectServiceImpl {
public void sayHello(String name) {
System.out.println("Hello "+name);
}
}
CglibProxyExample
package com.zw.proxyCGLiB;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CglibProxyExample implements MethodInterceptor {
/**
* 生成CGLIB对象
* @param cls ——Class类
* @return Class类的CGLIB代理对象
*/
public Object getProxy(Class cls) {
// CGLIB enhancer 增强类对象
Enhancer enhancer =new Enhancer();
// 设置增强类型
enhancer.setSuperclass(cls);
// 定义代理逻辑对象为当前对象,要求当前对象实现MethodIntercepoter方法
enhancer.setCallback(this);
// 生成并返回代理对象
return enhancer.create();
}
/**
* 代理逻辑方法
* @param proxy 代理对象
* @param methd 方法
* @param agrs 方法参数
* @param metthodsProxy 方法代理
* @return throwable 异常
*/
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
// TODO Auto-generated method stub
System.out.println("调用真实对象前");
// CGLIB反射调用真实对象方法
Object result =methodProxy.invokeSuper(proxy, args);
System.err.println("调用真实对象之后");
return result;
}
}
调用方法
package com.zw.proxyCGLiB;
public class ProxyTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
tesCGLIBProxy();
}
public static void tesCGLIBProxy() {
CglibProxyExample cpe=new CglibProxyExample();
ReflectServiceImpl obj=(ReflectServiceImpl)cpe.getProxy(ReflectServiceImpl.class);
obj.sayHello("12");
}
}
Java异常处理
Exception in thread "main" java.lang.NoClassDefFoundError: org/objectweb/asm/Type
根据java.lang.NoClassDefFoundError,可知缺少class 依赖,请百度“Exception in thread "main" java.lang.NoClassDefFoundError: org/objectweb/asm/Type” ,可知缺少asm.jar,请在浏览器上下载
“asm.jar 下载”. 安装jar包,运行程式,
拦截器概念
由于动态代理一般都是比较难理解,程序设计者设计一个拦截器接口供开发者使用,开发者只要知道拦截器接口的方法,含义和作用即可,无需知道动态代理是怎么实现的,用JDK动态代理来实现一个拦截器接口Interceptor
package com.zw.intercept;
public interface HelloWorld {
public void sayHelloWorld();
}
package com.zw.intercept;
public class HelloWorldImpl implements HelloWorld {
@Override
public void sayHelloWorld() {
// TODO Auto-generated method stub
System.out.println("Hello World");
}
}
package com.zw.intercept;
import java.lang.reflect.Method;
public interface Interceptor {
public boolean before(Object proxy, Object target, Method method, Object[] args);
public void around(Object proxy, Object target, Method method, Object[] args);
public void after(Object proxy, Object target, Method method, Object[] args);
}
这里定义了3个方法,before around after
3个方法的参数为:proxy代理对象,target真实对象, method方法,args 运行方法参数
package com.zw.intercept;
import java.lang.reflect.Method;
public class MyInterceptor implements Interceptor {
@Override
public boolean before(Object proxy, Object target, Method method, Object[] args) {
System.err.println("反射方法前逻辑");
return false;// 不反射原有的方法
}
@Override
public void after(Object proxy, Object target, Method method, Object[] args) {
System.err.println("反射方法后逻辑");
}
@Override
public void around(Object proxy, Object target, Method method, Object[] args) {
System.err.println("取代了被代理对象的方法");
}
}
它实现了所有的Interceptor接口方法
package com.zw.intercept;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class InterceptorJdkProxy implements InvocationHandler {
private Object target; //真实对象
private String interceptorClass = null;//拦截器全限定名
public InterceptorJdkProxy(Object target, String interceptorClass) {
this.target = target;
this.interceptorClass = interceptorClass;
}
/**
* 绑定委托对象并返回一个代理占位
*
* @param target 真实对象
* @return 代理对象占位
*/
public static Object bind(Object target, String interceptorClass) {
//取得代理对象
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InterceptorJdkProxy(target, interceptorClass));
}
@Override
/**
* 通过代理对象调用方法,首先进入这个方法
*
* @param proxy --代理对象
* @param method --方法,被调用方法
* @param args -- 方法参数
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (interceptorClass == null) {
//没有设置拦截器则直接返回原有的方法
return method.invoke(target, args);
}
Object result = null;
//ͨ通过反射生成拦截器
Interceptor interceptor =
(Interceptor) Class.forName(interceptorClass).newInstance();
//调用前置方法
if (interceptor.before(proxy, target, method, args)) {
//反射原有对象方法
result = method.invoke(target, args);
} else {//返回false执行around方法
interceptor.around(proxy, target, method, args);
}
//调用后置方法
interceptor.after(proxy, target, method, args);
return result;
}
}
package com.zw.intercept;
import java.lang.reflect.Method;
public class MyInterceptor implements Interceptor {
@Override
public boolean before(Object proxy, Object target, Method method, Object[] args) {
System.err.println("反射方法前逻辑");
return false;// 不反射原有的方法
}
@Override
public void after(Object proxy, Object target, Method method, Object[] args) {
System.err.println("反射方法后逻辑");
}
@Override
public void around(Object proxy, Object target, Method method, Object[] args) {
System.err.println("取代了被代理对象的方法");
}
}
package com.zw.intercept;
import com.zw.intercept.InterceptorJdkProxy;
import com.zw.intercept.*;
public class TestInterceptor {
public static void main(String[] args) {
// TODO Auto-generated method stub
testInterceptor();
testChain();
}
public static void testInterceptor() {
HelloWorld proxy =(HelloWorld)InterceptorJdkProxy.bind(new HelloWorldImpl(),
"com.zw.intercept.MyInterceptor");
proxy.sayHelloWorld();
}
public static void testChain() {
HelloWorld proxy1 = (HelloWorld) InterceptorJdkProxy.bind(
new HelloWorldImpl(), "com.zw.intercept.Interceptor2");
proxy1.sayHelloWorld();
}
}
责任链模式
public static void testChain() {
HelloWorld proxy1 = (HelloWorld) InterceptorJdkProxy.bind(
new HelloWorldImpl(), "com.lean.ssm.chapter2.intercept.Interceptor1");
HelloWorld proxy2 = (HelloWorld) InterceptorJdkProxy.bind(
proxy1, "com.lean.ssm.chapter2.intercept.Interceptor2");
HelloWorld proxy3 = (HelloWorld) InterceptorJdkProxy.bind(
proxy2, "com.lean.ssm.chapter2.intercept.Interceptor3");
proxy3.sayHelloWorld();
}
testChain() 责任链
责任链模式:优点:在于我们可以在传递链上加入新的拦截器。
缺点:是会增加代理和反射,而代理和反射的性能不高。
观察者模式
观察者模式定义了一种一对多的依赖关系,让多个观察者观察多个被观察者对象的状态,当被观察的状态发送变化时,会通知所有观察者,并让其自动更新自己。在java中 java.util.Observable
观察者
package com.lean.ssm.chapter2.observer;
import java.util.ArrayList;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
public class ProductList extends Observable {
private List<String> productList = null;//产品列表
private static ProductList instance;//类的唯一实例
private ProductList() {}//构建方法私有化
/**
* 取得唯一实例
* @return 产品列表唯一实例
*/
public static ProductList getInstance() {
if (instance == null) {
instance = new ProductList();
instance.productList = new ArrayList<String>();
}
return instance;
}
/**
* 增加观察者(电商接口)
* @param observer 观察者
*/
public void addProductListObserver(Observer observer) {
this.addObserver(observer);
}
/**
* 新增产品
* @param newProduct 新产品
*/
public void addProudct(String newProduct) {
productList.add(newProduct);
System.err.println("產品列表心增了產品"+newProduct);
this.setChanged();//设置被观察对象发生变化
this.notifyObservers(newProduct);//通知观察者,并传递新产品
}
}
这个类的基本内容和主要用法
- 构建方法私有化,避免通过new的方式创建对象,而是通过getInstance 方法获得产品列表单例,这里使用的是单例模式。
- addProductListObserver 可以增加一个电商接口(观察者)。
- 核心逻辑在addProduct方法上,在产品列表上增加了一个新的产品,然后调用setChanged方法。这个方法用于告知观察者当前被观察者发生了变化,如果没有,则无法触发其行为,最后通过notifyObservers告知观察者,让它们发送相应的动作,并将新产品为参数传递给观察者。
观察者
package com.lean.ssm.chapter2.observer;
import java.util.Observable;
import java.util.Observer;
public class JingDongObserver implements Observer {
@Override
public void update(Observable o, Object product) {
String newProduct = (String) product;
System.err.println("發送新產品"+newProduct+"同步到金東");
}
}
package com.lean.ssm.chapter2.observer;
import java.util.Observable;
import java.util.Observer;
public class TaoBaoObserver implements Observer {
@Override
public void update(Observable o, Object product) {
String newProduct = (String) product;
System.err.println("發送新產品"+newProduct+"淘寶商城");
}
}
package com.lean.ssm.chapter2.observer;
public class ObserverTest {
public static void main(String[] args) {
ProductList observable = ProductList.getInstance();
TaoBaoObserver taoBaoObserver = new TaoBaoObserver();
JingDongObserver jdObserver = new JingDongObserver();
observable.addObserver(jdObserver);
observable.addObserver(taoBaoObserver);
observable.addProudct("新增產品1");
}
}
掌握工厂抽象工厂模式
抽象工厂模式可以向客户端提供一个接口,使得客户端在不必指定产品的具体情况下,创建多个产品族中的产品对象
掌握Builder (构建)模式
package com.lean.ssm.chapter2.builder;
public class TicketBuilder {
public static Object builder(TicketHelper helper) {
System.out.println("ͨ通过TicketHelper构建套票信息");
return null;
}
}
package com.lean.ssm.chapter2.builder;
public class TicketHelper {
public void buildAdult(String info) {
System.err.println("构建成人票逻辑" + info);
}
public void buildChildrenForSeat(String info) {
System.err.println("构建有座儿童票逻辑" + info);
}
public void buildchildrenNoSeat(String info) {
System.err.println("构建无座儿童票逻辑" + info);
}
public void buildElderly(String info) {
System.err.println("构建有老人票逻辑" + info);
}
public void buildSoldier(String info) {
System.err.println("构建军人及其家属逻辑" + info);
}
}
package com.lean.ssm.chapter2.builder;
public class BuilderTest {
public static void main(String[] args) {
TicketHelper helper = new TicketHelper();
helper.buildAdult("成人票");
helper.buildChildrenForSeat("有座儿童票");
helper.buildchildrenNoSeat("无座儿童票");
helper.buildElderly("老人票");
helper.buildSoldier("军人票");
Object ticket = TicketBuilder.builder(helper);
}
}