装饰器模式
在不改变源代码的基础上对一个对象的功能进行增强
可以对一个对象装饰多个功能
Java实现
1.实现和原对象一样的接口
2.重写需要增强的方法
原始未增强的代码
接口
public interface MyInter {
public void print(String s);
}
原始类
public class Source implements MyInter {
@Override
public void print(String s) {
System.out.println(s);
}
}
测试类
public static void main(String[] args) throws Exception {
MyInter source = new Source();
source.print("aaa");//aaa
}
对print方法进行增强,将所有小写字符串改为大写
即MyInter source对象调用自身print方法时进行增强
1.print方法只属于MyInter类型
所以要增强就必须要增强类实现MyInter接口
2.增强类要重写print方法,这样在调用MyInter.print时,
就可以太子换狸猫,调用增强类的print方法
为了在增强类中执行原始类的print方法
必须将原始类作为增强类的属性,在构造器中初始化
就可以在增强类中调用并对其进行增强
装饰器1
public class Decorate implements MyInter {
private MyInter source;//接口类型的原始类作为属性
public Decorate() {
super();
}
public Decorate(MyInter source) {//初始化
super();
this.source = source;
}
@Override
public void print(String s) {
System.out.println("Decorate增强前执行的代码...");
s = s.toUpperCase();//字母全大写
source.print(s);//将大写字母作为参数
System.out.println("Decorate增强后执行的代码...");
}
}
装饰器2
public class Decorate2 implements MyInter {
private MyInter source;
public Decorate2() {
super();
}
public Decorate2(MyInter source) {
super();
this.source = source;
}
@Override
public void print(String s) {
System.out.println("Decorate2 增强前执行的代码...");
s = s.toLowerCase();//转为全小写
source.print(s);//将小写字母作为参数
System.out.println("Decorate2 增强后执行的代码...");
}
}
测试代码
public static void main(String[] args) throws Exception {
MyInter s1 = new Source();
MyInter source = new Decorate2(new Decorate(s1));
source.print("aaa");
//执行的是装饰器2的增强方法
//将字母转为小写并作为参数传入装饰器1的增强方法,并调用装饰器1的增强方法
//在装饰器1的增强方法中,将字符串转为大写,再调用原始类的方法输出字符串
/* Decorate2 增强前执行的代码...
Decorate 增强前执行的代码...
AAA
Decorate 增强后执行的代码...
Decorate2 增强后执行的代码...
*/
}
实际应用
servlet中的request.getParameter("username")
对于get请求的乱码问题需要单独对参数进行编码与解码
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String parameter = request.getParameter("username");
System.out.println(parameter);
}
这个时候就可以对其进行增强
在过滤器Filter中拦截所有请求,在doFilter方法中进行调用增强类
1.HttpServletRequest request有一个父类接口HttpServletRequestWrapper,
自定义MyRequest实现这个接口
2.重写getParameter方法
public class MyRequest extends HttpServletRequestWrapper{
private HttpServletRequest request;
//有参构造
public MyRequest(HttpServletRequest request) {
super(request);
this.request = request;
}
//无参构造
//...
//对getParaameter增强
@Override
public String getParameter(String name) {
String parameter = request.getParameter(name);//乱码
try {
parameter = new String(parameter.getBytes("iso8859-1"),"UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return parameter;
}
}
增强后在Filter中用MyRequest替换(HttpServletRequest
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
//post方式乱码的解决代码
request.setCharacterEncoding("UTF-8");
//get方式乱码的解决代码
HttpServletRequest req = (HttpServletRequest) request;
//增强对象
MyRequest myRequest = new MyRequest (req);
//替换对象,放行请求
chain.doFilter(myRequest , response);
}
python实现
使用装饰器计算出代码运行时间
def function(f):
def inner(*args,**kwagrs):
start = time.time()#目标方法运行前执行的代码
ret = f(*args,**kwagrs)#目标方法
end =time.time() - start#目标方法运行后执行的代码
print('程序运行时间为%.4f'% end)
return ret #方法返回值
return inner
@function
def code(n):
for i in range(n):
print(i)
code(10000)
print(code.__name__)#inner
将函数装饰器转换为方法装饰器
from django.utils.decorators import method_decorator
class MyTest(Object):
@method_decorator(function)
def code(n):
for i in range(n):
print(i)