1.装饰者模式定义
动态地给一个对象添加一些额外的职责。就增加功能来说, 装饰模式相比生成子类更为灵活。
------《设计模式之禅》
2.通用类图:
类图说明:
● Component抽象构件
Component是一个接口或者是抽象类, 就是定义我们最核心的对象, 也就是最原始的对象。
注意: 在装饰模式中, 必然有一个最基本、 最核心、 最原始的接口或抽象类充当Component抽象构件。
● ConcreteComponent 具体构件
ConcreteComponent是最核心、 最原始、 最基本的接口或抽象类的实现, 你要装饰的就是它。
● Decorator装饰角色
一般是一个抽象类, 做什么用呢? 实现接口或者抽象方法, 它里面可不一定有抽象的方法呀,
在它的属性里必然有一个private变量指向Component抽象构件。
● 具体装饰角色
ConcreteDecoratorA和ConcreteDecoratorB是两个具体的装饰类,
你要把你最核心的、 最原始的、 最基本的东西装饰成其他东西。
------《设计模式之禅》
3.类图代码:
public abstract class Component {
//抽象的方法
public abstract void operate();
}
public class ConcreteComponent extends Component {
//具体实现
@Override
public void operate() {
System.out.println("do Something");
}
}
public abstract class Decorator extends Component {
private Component component = null;
//通过构造函数传递被修饰者
public Decorator(Component _component){
this.component = _component;
}
//委托给被修饰者执行
@Override
public void operate() {
this.component.operate();
}
}
public class ConcreteDecorator1 extends Decorator {
//定义被修饰者
public ConcreteDecorator1(Component _component){
super(_component);
}
//定义自己的修饰方法
private void method1(){
System.out.println("method1 修饰");
}
//重写父类的Operation方法
public void operate(){
this.method1();
super.operate();
}
}
servlet过滤器之网页压缩
应用: 如今租赁的服务器有的是按照流量来节省流量,所以网页压缩技术有助于节省流量,
并且可以提高用户的网的响应速度,大大提高了用户体验。
所用技术:
- java 的GZIPOutputStream类进行gzip压缩。
- 通过javaweb的过滤器,对服务端发响应的数据进行压缩。
- 装饰者模式,对已经存在的方法进行重写。
分析:
- 运用过滤器,对服务器每一次的响应的数据进行gzip压缩。
- 在servlet中的response.getwriter().writer()向客户端发送数据,可是中间的数据无法再过滤器中截取。
- 以上,所以需要重写response中的PrintWriter方法,将响应数据在发送到客户端之前先保存到ServletResponse的成员缓冲区中。
- 随后在过滤器中将响应内容进行压缩,再发送给客户端。
过滤器代码
public class GIZPFilter implements Filter {
public GIZPFilter() {
}
public void destroy() {
}
public void init(FilterConfig fConfig) throws ServletException {
}
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
//对响应中的数据先进行编码
req.setCharacterEncoding("utf-8");
//对response进行装饰
HttpServletResponse response = (HttpServletResponse) res;
//进行包装
MyHttpResponse myResponse = new MyHttpResponse(response);
//放行,在servlet向缓冲区中写数据
chain.doFilter(req, myResponse);
//获取缓冲区中的内容
char[] content = myResponse.getBuf().toCharArray();
//创建缓冲区
ByteArrayOutputStream bos = new ByteArrayOutputStream();
//进行压缩
GZIPOutputStream gzip = new GZIPOutputStream(bos);
//向bos2缓冲区中写入数据
gzip.write(new String(content).getBytes());
//刷新缓冲区
gzip.finish();
System.out.println("压缩后的数据大小:" + new String(bos.toByteArray()).length());
System.out.println(new String(content));
//设置响应体中的字体
myResponse.setContentType("text/html;charset=utf-8");
//设置浏览器解析格式
myResponse.setHeader("content-encoding", "gzip");
//向浏览器写数据
myResponse.getOutputStream().write(bos.toByteArray());
}
}
//重写的类
class MyHttpResponse extends HttpServletResponseWrapper {
private HttpServletResponse response = null;
//定义缓冲区
private CharArrayWriter buf = new CharArrayWriter();
public CharArrayWriter getBuf() {
return buf;
}
public MyHttpResponse(HttpServletResponse response) {
super(response);
this.response = response;
}
@Override
public PrintWriter getWriter() throws IOException {
//创建带缓冲区的PrintWriter对象(API中可查)
return new PrintWriter(buf);
}
}
服务器代码:
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//准备数据
StringBuffer sb = new StringBuffer();
for(int i=1;i<=3000;i++){
sb.append("abcd你好");
}
System.out.println("压缩前的数据大小: "+sb.toString().getBytes().length);
//这里的response已经是过滤器中定义的MyHttpResponse 类
PrintWriter out = response.getWriter();
out.write(sb.toString());
//关闭并刷新缓冲区
out.close();
}