JAVA语言之结构型设计模式
小标 2019-05-09 来源 : 阅读 718 评论 0

摘要:本文主要向大家介绍了JAVA语言之结构型设计模式,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助。

本文主要向大家介绍了JAVA语言之结构型设计模式,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助。

JAVA语言之结构型设计模式

架构型设计模式成员



  • 门面模式


  • 代理模式


  • 装饰器模式


  • 组合模式


  • 享元模式


  • 桥接模式


  • 适配器模式



1. 代理模式


1.1 定义


为其他对象提供一种代理以控制对这个对象的访问 


解决问题:在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层


1.2 分类


1.2.1 静态代理



  • 一个代理类只能对一个业务接口的实现类进行包装,如果有多个业务接口的话就要定义很多实现类和代理类才行


  • 而且,如果代理类对业务方法的预处理、调用后操作都是一样的(比如:调用前输出提示、调用后自动关闭连接),则多个代理类就会有很多重复代码



接口类

package com.zhunongyun.spring.proxy;

public interface Image {
   void display();

   void change(String imagePath);
}

--------------------------------------------------

接口的实现类

package com.zhunongyun.spring.proxy;

public class RealImage implements Image {

   private String fileName;

   public RealImage(String fileName){
      this.fileName = fileName;
      loadFromDisk(fileName);
   }

   @Override
   public void display() {
      System.out.println("显示图片: " + fileName);
   }

   @Override
   public void change(String imagePath) {
      System.out.println("替换图片: " + imagePath);
   }

   private void loadFromDisk(String fileName){
      System.out.println("加载图片: " + fileName);
   }
}

-------------------------------------------------------

代理类

package com.zhunongyun.spring.proxy;

public class ProxyImage implements Image{

   private RealImage realImage;
   private String fileName;

   public ProxyImage(String fileName){
      this.fileName = fileName;
   }

   @Override
   public void display() {
      if(realImage == null){
         realImage = new RealImage(fileName);
      }
      realImage.display();
   }

   @Override
   public void change(String imagePath) {
      if(realImage == null){
         realImage = new RealImage(fileName);
      }
      realImage.change(imagePath);
   }
}

---------------------------------------------------

测试类

package com.zhunongyun.spring.proxy;

public class ProxyPatternDemo {

   public static void main(String[] args) {
      Image image = new ProxyImage("test_10mb.jpg");

      // 图像将从磁盘加载
      image.display();
      System.out.println("---------------------");
      // 图像不需要从磁盘加载
      image.display(); 
   }
}

输出结果:
加载图片: test_10mb.jpg
显示图片: test_10mb.jpg
---------------------
显示图片: test_10mb.jpg


1.2.2 动态代理


1.2.2.1  JDK 自带的动态代理



  • java.lang.reflect.Proxy: 生成动态代理类和对象


  • java.lang.reflect.InvocationHandler(处理器接口):可以通过invoke方法实现对真实角色的代理访问



每次通过 Proxy 生成的代理类对象都要指定对应的处理器对象 


接口类

package com.zhunongyun.spring.proxy.dynamic;

public interface Subject {
    int sellBooks();

    String speak();
}

---------------------------------------------------------

接口实现类

package com.zhunongyun.spring.proxy.dynamic;

public class RealSubject implements Subject{
    @Override
    public int sellBooks() {
        System.out.println("卖书");
        return 1 ;
    }

    @Override
    public String speak() {
        System.out.println("说话");
        return "张三";
    }
}

------------------------------------------------------------------

动态代理类

package com.zhunongyun.study.toalibaba.spring.proxy.dynamic;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 定义一个处理器
 *
 * @author gnehcgnaw
 * @date 2018/11/5 19:26
 */
public class MyInvocationHandler implements InvocationHandler {
    /**
     * 这其实业务实现类对象,用来调用具体的业务方法
     */
    private Object target;

    /**
     * 绑定业务对象并返回一个代理类
     */
    public Object bind(Object target) {
        //接收业务实现类对象参数
        this.target = target;

        //通过反射机制,创建一个代理类对象实例并返回。用户进行方法调用时使用
        //创建代理对象时,需要传递该业务类的类加载器(用来获取业务实现类的元数据,在包装方法是调用真正的业务方法)、接口、handler实现类
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(), this);
    }

    /**
     * @param proxy  代理类
     * @param method 正在调用的方法
     * @param args   方法的参数
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        Object result=null;

        System.out.println("预处理操作——————");
        //调用真正的业务方法 
        result=method.invoke(target, args);

        System.out.println("调用后处理——————");
        return result;
    }
}

-------------------------------------------------------------------

测试类

package com.zhunongyun.spring.proxy.dynamic;

import java.lang.reflect.Proxy;

/**
 * 调用类
 * @author gnehcgnaw
 * @date 2018/11/7 20:26
 */
public class Client {
    public static void main(String[] args) {
        //真实对象
        Subject realSubject =  new RealSubject();

        MyInvocationHandler myInvocationHandler = new MyInvocationHandler(realSubject);
        //代理对象
        Subject proxyClass = (Subject) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Subject.class}, myInvocationHandler);

        proxyClass.sellBooks();

        proxyClass.speak();
    }
}

------------------------------------------------------------------------
输出结果:

预处理操作——————
卖书
调用后处理——————
预处理操作——————
说话
调用后处理——————


1.2.2.2 CGlib动态代理


操作类

package com.zhunongyun.study.toalibaba.spring.proxy.cglib;

public class BookFacadeImpl {
    public void addBook() { 
        System.out.println("新增图书..."); 
    } 


-------------------------------------------

CGlib代理类

package com.zhunongyun.study.toalibaba.spring.proxy.cglib;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class BookFacadeCglib implements MethodInterceptor {
    /**
     * 业务类对象,供代理方法中进行真正的业务方法调用
     */
    private Object target;

    /**
     * 相当于JDK动态代理中的绑定
     * @param target
     * @return
     */
    public Object getInstance(Object target) {
        //给业务对象赋值
        this.target = target;

        //创建加强器,用来创建动态代理类
        Enhancer enhancer = new Enhancer();

        //为加强器指定要代理的业务类(即:为下面生成的代理类指定父类)
        enhancer.setSuperclass(this.target.getClass());

        //设置回调:对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实现intercept()方法进行拦
        enhancer.setCallback(this);

        // 创建动态代理类对象并返回
        return enhancer.create();
    }

    /**
     * 实现回调方法
     * @param obj
     * @param method
     * @param args
     * @param proxy
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("预处理——————");

        //调用业务类(父类中)的方法
        proxy.invokeSuper(obj, args);
        System.out.println("调用后操作——————");
        return null;
    }
}

------------------------------------------------

测试类

package com.zhunongyun.study.toalibaba.spring.proxy.cglib;

public class CglibDemo {
    public static void main(String[] args) {
        BookFacadeImpl bookFacade = new BookFacadeImpl();

        BookFacadeCglib cglib = new BookFacadeCglib();

        BookFacadeImpl bookCglib = (BookFacadeImpl) cglib.getInstance(bookFacade);

        bookCglib.addBook();
    }
}

----------------------------------------

输出结果

预处理——————
新增图书...
调用后操作——————


1.2.2.3 JDK动态代理与CGlib动态代理



  • JDK动态代理是通过接口中的方法名,在动态生成的代理类中调用业务实现类的同名方法


  • CGlib动态代理是通过继承业务类,生成的动态代理类是业务类的子类,通过重写业务方法进行代理


   

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注编程语言JAVA频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程