设计模式之结构性模式(一)

设计模式之结构性模式(一)

一、适配器模式
二、代理模式

核心作用:从程序的结构上实现松耦合,从而可以扩大整体的类结构,解决更大的问题
分类:适配器模式、代理模式、桥接模式、装饰模式、组合模式、外观模式、享元模式

一、适配器模式

将一个类的接口转换成客户希望的另一个接口,可以使原本由于接口不兼容而不能一起工作的类可以一起工作

模式中的角色:

目标接口(Target):客户所期待的接口,目标可以是具体的或抽象的类,也可以是接口
需要适配的类(Adaptee):需要适配的类或适配者的类
适配器(Adapter):通过包装一个需要适配的对象,把原接口转换成目标接口
在这里插入图片描述

实例:电脑(Client) 转换器(Adapter) 键盘(Adaptee)

Adaptee

/**
 * 被适配的类(相当于键盘)
 */
package com.adapter;

public class Adaptee {
    //需求
    public void request() {
    	System.out.println("可以完成客户端请求需要的功能");
    }

}

Adapter(类适配器)

/**
 * 适配器(相当于转接器,USB)
 */
package com.adapter;

public class Adapter extends Adaptee implements Target{
@Override
public void handleRequest() {
    super.request();
    }
}

Target

//目标接口
package com.adapter;

public interface Target {
//处理需求的方法
public void handleRequest();
}

Adapter2(对象是适配器)

/**
 * 适配器(相当于转接器)
 */
package com.adapter;

public class Adapter2 implements Target {
    Adaptee adaptee;
    
    public Adapter2(Adaptee adaptee) {
    super();
    this.adaptee = adaptee;
}

@Override
public void handleRequest() {
    adaptee.request();
 }
}

Client

/**
 * 客户端类(相当于笔记本,只有USB接口)
 */
package com.adapter;

public class Client {

public void test(Target t) {
	t.handleRequest();
}

public static void main(String[] args) {
    Client laptop = new Client();//电脑(客户端)
    Adaptee keyboard = new Adaptee();//键盘(适配的类)
    //Target adapter = new Adapter();//适配器(转换器)
    Target adapter = new Adapter2(keyboard);//适配器(转换器)
    laptop.test(adapter);
    }
}

结果:

可以完成客户端请求需要的功能

二、代理模式

核心作用:通过代理,控制对对象的访问
可以详细控制访问某个对象的方法,在调用这个方法前做前置处理,调用这个方法后做后置处理(AOP的微观实现)
AOP:Aspect Oriented Progrmming 面向切面编程的核心机制

核心角色:
抽象角色:定义代理角色和真实角色的公共对外方法
真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用(关注真正的业务逻辑)
代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作(将统一的流程控制放到代理角色中处理)
在这里插入图片描述

应用场景:
安全代理:屏蔽对真实角色的直接访问
远程代理:通过代理类处理远程方法调用(RMI)
延时加载:先加载轻量级的代理对象,真正需要再加载真实对象
(比如开发一个大文档查看软件,大文档中有大的图片,有可能一个图片有100MB,在打开文件时,不可能将所有文件都显示出来,这样就可以使用代理模式,当需要查看图片时,用proxy来进行大图片的打开)

分类:
静态代理(静态定义代理类)
动态代理(动态定义代理类)
1)JDK自带的动态代理
2)javaassist字节码操作库实现
3)CGLIB
4)ASM(底层使用指令,可维护性较差)

静态代理类

实例:明星 明星代理人

Star

/**
 * 明星接口
 */
package com.proxy.staticProxy;

public interface Star {
    public void confer();//面谈
    public void signContract();//签合同
    public void bookTicket();//订机票
    public void sing();//唱歌
    public void collectMoney();//收钱
}

RealStar

/**
 * 明星本人
 */
package com.proxy.staticProxy;

public class RealStar implements Star {
    @Override
    public void confer() {
    System.out.println("RealStar.confer()");
}

@Override
    public void signContract() {
    System.out.println("RealStar.signContract()");
}

@Override
    public void bookTicket() {
    System.out.println("RealStar.bookTicket()");
}

@Override
    public void sing() {
    System.out.println("RealStar.sing()(明星本人)");
}

@Override
public void collectMoney() {
    System.out.println("RealStar.collectMoney()");
    }
}

ProxyStar

/**
 * 明星代理人
 */
package com.proxy.staticProxy;

public class ProxyStar implements Star {

    @Override
    public void confer() {
    	System.out.println("ProxyStar.confer()");
    }
    
    @Override
    public void signContract() {
    	System.out.println("ProxyStar.signContract()");
    }
    
    @Override
    public void bookTicket() {
   		System.out.println("ProxyStar.bookTicket()");
    }
    
    @Override
    public void sing() {
  	  System.out.println("RealStar.sing()");
    }
    
    @Override
    public void collectMoney() {
  	  System.out.println("ProxyStar.collectMoney()");
    }
}

Client

/**
 * 测试函数
 */
package com.proxy.staticProxy;

public class Client {
    public static void main(String[] args) {
	    Star realStar = new RealStar();
	    Star proxyStar = new ProxyStar();
	    
	    proxyStar.confer();
	    proxyStar.bookTicket();
	    proxyStar.signContract();
	    proxyStar.collectMoney();
	    proxyStar.sing();
    }
}

结果

ProxyStar.confer()
ProxyStar.bookTicket()
ProxyStar.signContract()
ProxyStar.collectMoney()
RealStar.sing()//注意

动态代理类

JDK自带的动态代理

在这里插入图片描述

Star

RealStar

StarHandler

package dynasticProxy;

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

public class StarHandler implements InvocationHandler {//处理器接口

    //创建真实的明星
    Star realStar = null;
    
    //构造器
    public StarHandler(Star realStar) {
	    super();
	    this.realStar = realStar;
    }
    
    //通过invoke()方法实现对真实角色的代理访问
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
	    Object object = null;
	    
	    System.out.println("真正的方法执行前");
	    System.out.println("面谈、签合同、待付款、订机票");
	    
	    //如果是sing,就调用realStar()方法
	    if(method.getName().equals("sing")) {
	   	 object = method.invoke(realStar, args);
	    }
	    
	    System.out.println("真正的方法执行后");
	    System.out.println("收尾款");
	    return object;
    }
}

Client

package dynasticProxy;

import java.lang.reflect.Proxy;

public class Client {
    public static void main(String[] args) {
	    Star realStar = new RealStar();
	    StarHandler handler = new StarHandler(realStar);
	    
	    //每次通过Proxy生成代理类处理对象时,都要指定对应的处理器对象
	    Star proxy = (Star) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),new Class[]{Star.class} ,handler );
	    
	    proxy.sing();
    }
}

结果:

真正的方法执行前
面谈、签合同、待付款、订机票
RealStar.sing()(明星本人)
真正的方法执行后
收尾款

代理模式开发框架中应用场景:

数据库连接池关闭处理
mybatis中实现拦截器插件
Aspect的实现
String中AOP的实现(日志拦截、声明式事务处理)
web service
RMI远程方法调用

面向切面编程常用术语:

切面:共有功能的实现
通知:切面的具体实现
连接点:程序在运行过程中能够插入切面的地点
切入点:用于定义应该切入到那些连接点上
目标对象:即将切入切面的对象,即被通知的对象
代理对象L:通知应用到目标对象之后被动态创建的对象
织入:将切面应用到目标对象从而创建一个新的代理对象的过程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值