装饰者模式:
定义
在不改变原有对象的基础之上,将功能附加到对象上。提供了比继承更有弹性的替代方案(扩展原有对象功能)
类型
结构型
适用场景
- 扩展一个类的功能或者给一个类添加附加职责
- 给一个对象动态的添加功能,或动态撤销功能。
动态代理模式:
定义
代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。通俗的来讲代理模式就是我们生活中常见的中介。代理模式是常用的结构型设计模式之一,它为对象的间接访问提供了一个解决方案,可以对对象的访问进行控制。代理模式类型较多,其中远程代理、虚拟代理、保护代理等在软件开发中应用非常广泛。
类型
结构型
适用场景
1:类中的方法批量处理
2:方法的区分处理
3:当我们想要隐藏某个类,或者这个类中的部分方法
4:扩展功能
通过一个代理类完成全部的代理功能,那么我们就需要用动态代理.
一个代理只能代理一种类型,而且是在编译器就已经确定被代理的对象。而动态代理是在运行时,通过反射机制实现动态代理,并且能够代理各种类型的对象。
在Java中要想实现动态代理机制,需要java.lang.reflect.InvocationHandler
接口和java.lang.reflect.Proxy
类的支持。
为什么要使用代理模式?
- 中介隔离作用:在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的作用,其特征是代理类和委托类实现相同的接口。
- 开闭原则,增加功能:代理类除了是客户类和委托类的中介之外,我们还可以通过给代理类增加额外的功能来扩展委托类的功能,这样做我们只需要修改代理类而不需要再修改委托类,符合代码设计的开闭原则。代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后对返回结果的处理等。代理类本身并不真正实现服务,而是同过调用委托类的相关方法,来提供特定的服务。真正的业务功能还是由委托类来实现,但是可以在业务功能执行的前后加入一些公共的服务。例如我们想给项目加入缓存、日志这些功能,我们就可以使用代理类来完成,而没必要打开已经封装好的委托类。
================================================================================================================================================================================================
案例:装饰者模式:
Test.java
public class Test {
public static void main(String[] args) {
LvJing lvJing = new LvJing(new iPhone());
lvJing.takePhone();
}
}
Phone.java
public interface Phone {
public void takePhone();
public void call();
}
iPhone.java
public class iPhone implements Phone{
@Override
public void takePhone() {
System.out.println("iphone拍照");
}
@Override
public void call() {
System.out.println("iphone打电话");
}
}
iPhoneWrap.java
public abstract class iPhoneWrap implements Phone {
private Phone phone;
public iPhoneWrap(Phone phone ) {
this.phone = phone;
}
@Override
public void takePhone() {
phone.takePhone();
}
@Override
public void call() {
phone.call();
}
}
MeiYan.java
public class MeiYan extends iPhoneWrap {
public MeiYan(Phone phone) {
super(phone);
}
@Override
public void takePhone() {
super.takePhone();
System.out.println("增加美颜功能");
}
}
此案例就是对装饰者模式的基础,还可以进行增加扩展功能、
Filter装饰者模式的应用:
@WebFilter("/WordsProServlet")
public class WordsProFilter implements Filter {
private List<String> wordsList;
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
HttpMyRequest httpMyRequest = new HttpMyRequest(request, wordsList);
String content = httpMyRequest.getParameter("content");
chain.doFilter(httpMyRequest, response);
}
public void init(FilterConfig config) throws ServletException {
System.out.println("=======WordsProFilter=========过滤器=================");
Properties properties = new Properties();
InputStream words = this.getClass().getResourceAsStream("/words.properties");
try {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(words, "utf-8"));
properties.load(bufferedReader);
} catch (IOException e) {
e.printStackTrace();
}
String keywords = properties.getProperty("keywords");
List<String> wordsList = Arrays.asList(keywords.split(","));
this.wordsList = wordsList;
}
}
装饰模式的扩展类:对HttpServletRequest 进行扩展
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.util.List;
public class HttpMyRequest extends HttpServletRequestWrapper {
private List<String> wordsList;
public HttpMyRequest(HttpServletRequest request,List<String> list) {
super(request);
this.wordsList =list;
}
@Override
public String getParameter(String name) {
String content = super.getParameter(name);
for (String word : wordsList) {
if (content.contains(word)){
String flagStr ="";
for (int i = 0; i < word.length(); i++) {
flagStr+="*";
}
content = content.replaceAll(word,flagStr);
}
}
return content;
}
}
================================================================================================================================================================================================
动态代理模式实现案例:
实现步骤:JDK:要求目标对象和代理对象,实现同一个接口
1.创建目标对象(过滤器已提供)
2.通过Proxy工具,生产代理类,创建代理对象
3.放行代理对象
通过Proxy代理实现过滤:
@WebFilter("/WordsProProxyFilter")
public class WordsProProxyFilter implements Filter {
private List<String> wordsList;
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//设置请求解码方式
req.setCharacterEncoding("utf-8");
//设置响应编码方式
resp.setContentType("text/html;charset=utf-8");
// 1.创建目标对象(过滤器已提供 ServletRequest req)
// 2.通过Proxy工具,生产代理类,创建代理对象
/*
类加载器:目标对象的加载器
接口数组:目标对象的接口数组
处理器接口:创建匿名内部类,实现增强业务逻辑
*/
ServletRequest servletRequest =(ServletRequest) Proxy.newProxyInstance(req.getClass().getClassLoader(), req.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//目标对象实现具体功能
Object object = method.invoke(req, args);
//如果执行了getParameter方法,,实现对内容增强,过滤
if ("getParameter".equals(method.getName())){
String msg = (String) object;
for (String word : wordsList) {
if (msg.contains(word)){
msg=msg.replaceAll(word,"***");
}
}
//返回结果
return msg;
}
//返回结果
return object;
}
});
//放行代理对象
chain.doFilter(servletRequest, resp);
}
public void init(FilterConfig config) throws ServletException {
System.out.println("=======WordsProProxyFilter=========过滤器=================");
Properties properties = new Properties();
InputStream words = this.getClass().getResourceAsStream("/words.properties");
try {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(words, "utf-8"));
properties.load(bufferedReader);
} catch (IOException e) {
e.printStackTrace();
}
String keywords = properties.getProperty("keywords");
List<String> wordsList = Arrays.asList(keywords.split(","));
this.wordsList = wordsList;
}
}
资料: