设计模式
1. 工厂模式
工厂模式属于创建型模式,在工厂模式中,我们创建对象时不会暴露创建逻辑,而是通过一个共同的接口来指向新创建的对象。
在任何需要生成复杂对象的地方,都可以使用工厂模式,而对于简单对象,特别是只需要new来创建的对象,如果引入工厂类反而会增加系统的复杂度。
应用场景:在Spring框架中,当我们需要框架生成对象时,会使用工厂注入的方式
例:假设我们需要一个交通工具,可以直接从工厂里提货,而不用管是怎么做出来的,具体代码如下
1.1 静态工厂
创建一个Transportation接口
public interface Transportation {
public void run();
}
创建Transportation接口的实现类
//创建汽车类
class Car implements Transportation {
@Override
public void run() {
System.out.println("在路上跑");
}
}
//创建飞机类
class Plane implements Transportation {
@Override
public void run() {
System.out.println("在天上飞");
}
}
//创建轮船类
class Boat implements Transportation {
@Override
public void run() {
System.out.println("在水上开");
}
}
创建一个静态工厂类
public class StaticFactory {
public static Transportation getTransportation(String type){
if (type==null){
return null;
}
else if ("car".equals(type)){
return new Car();
}
else if ("plane".equals(type)){
return new Plane();
}
else if ("boat".equals(type)){
return new Boat();
}else {
return null;
}
}
}
测试
public class TestStaticFac {
public static void main(String[] args) {
Car car = (Car) StaticFactory.getTransportation("car");
car.run();
Plane plane = (Plane) StaticFactory.getTransportation("plane");
plane.run();
Boat boat = (Boat) StaticFactory.getTransportation("boat");
boat.run();
}
}
/*
运行结果:在路上跑
在天上飞
在水上开
*/
1.2 实例化工厂
创建一个实例化工厂类
public class StaticFactory {
public Transportation getTransportation(String type){
if (type==null){
return null;
}
else if ("car".equals(type)){
return new Car();
}
else if ("plane".equals(type)){
return new Plane();
}
else if ("boat".equals(type)){
return new Boat();
}else {
return null;
}
}
}
测试
public class TestUserFac {
public static void main(String[] args) {
UserFactory uf = new UserFactory();
Car car = (Car) uf.getTransportation("car");
car.run();
Plane plane = (Plane) uf.getTransportation("plane");
plane.run();
Boat boat = (Boat) uf.getTransportation("boat");
boat.run();
}
}
/*
运行结果:在路上跑
在天上飞
在水上开
*/
2. 代理模式
代理模式在Java开发中是一种比较常见的设计模式,设计目的旨在为服务类和客户类之间插入其他功能,像生活中常见的中介,婚庆公司就属于代理模式,代理模式的两个设计原则:
- 代理类和委托类具有相似的行为
- 代理类增强委托类的行为
代理的三要素:
- 有共同的行为(接口)
- 目标对象(实现行为)
- 代理对象(增强目标对象行为)
应用场景:Spring框架中的AOP(面向切面编程)底层就是动态代理模式
2.1 静态代理
静态代理中代理对象是固定的,我们用常用的的婚礼为例来阐述静态代理,该例中婚庆公司作为代理对象是确定的,具体谁结婚可以改变。
定义Marry接口:
public interface Marry {
public void toMarry();
}
定义目标对象类:
public class You implements Marry {
@Override
public void toMarry() {
System.out.println("举办婚礼");
}
}
定义代理对象类:
public class MarryCompany implements Marry {
private Marry marry;
public MarryCompany(Marry marry) {
this.marry = marry;
}
@Override
public void toMarry() {
//before
System.out.println("布置会场");
marry.toMarry();
//after
System.out.println("收拾会场");
}
}
测试:
public class TestMarry {
@Test
public void testMarry(){
MarryCompany mc = new MarryCompany(new You());
mc.toMarry();
}
/*
运行结果:
布置会场
举办婚礼
收拾会场
*/
}
2.2 动态代理
动态代理的代理对象,目标对象都不确定,因此会更加的灵活,代理对象由Java反射机制动态产生。动态代理的两种实现方式:
- JDK动态代理
- CGLIB动态代理
2.2.1 JDK动态代理
JDK动态代理的目标对象必须有接口实现
以上述的婚礼为例,定义Marry接口和目标对象类后定义动态代理对象类如下:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JdkHandler implements InvocationHandler {
private Object target;
public JdkHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before...");
//调用目标对象的指定方法
Object result = method.invoke(target, args);
System.out.println("after...");
return result;
}
//定义获取代理对象的方法
public Object getProxy(){
Object result = Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
return result;
}
}
测试:
@Test
public void testJdk(){
You you = new You();
JdkHandler jh = new JdkHandler(you);
Marry proxy = (Marry) jh.getProxy();
proxy.toMarry();
}
/*
运行结果:
before...
举办婚礼
after...
*/
2.2.2 CGLIB动态代理
CGLIB动态代理的对象没有限制,无接口实现也可以使用。
定义动态代理对象类:
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CgLibHanlder implements MethodInterceptor {
private Object target;
public CgLibHanlder(Object target) {
this.target = target;
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("before...");
Object result = method.invoke(target, objects);
System.out.println("after...");
return result;
}
public Object getProxy(){
Enhancer eh = new Enhancer();
eh.setSuperclass(target.getClass());
eh.setCallback(this);
return eh.create();
}
}
定义无接口实现的目标对象类:
public class User {
public void haha(){
System.out.println("哈哈哈");
}
}
测试:
@Test
public void testCglib(){
You you = new You();
CgLibHanlder ch = new CgLibHanlder(you);
User user = new User();
CgLibHanlder ch2 = new CgLibHanlder(user);
//与jdk相比可不用父类接口
You proxy = (You) ch.getProxy();
proxy.toMarry();
//类不实现接口也可以
User proxy2 = (User) ch2.getProxy();
proxy2.haha();
}
/*
运行结果:
before...
举办婚礼
after...
before...
哈哈哈
after...
*/