装饰者模式

装饰者模式

什么是装饰者模式

  • 作用:对一个类的功能进行增强,对现有类中的方法进行重写,增强原有的方法功能,以多次增强。采用继承的方式对现有的类进行功能增强

image

概念:

如果要对一个类的功能进行增强,又不能修改原来类的源代码,可以使用装饰者模式。

  • 特点:采用继承的方式,重写父类原有的方法,在重写的子类方法中调用父类的方法,并且对父类的方法进行增强。
  • 使用场景:

    • 一切需要对类中的方法进行增强场景,而且又不能修改原来的代码。
装饰者模式中的角色:
  1. 抽象角色:是一个接口或抽象类,定义真实角色具有哪些功能。
  2. 真实角色:实现了抽象角色,并且实现了接口中所有的方法。
  3. 装饰角色:用于对真实角色的功能进行增强的类,继承于真实角色,并且重写真实角色中需要增强的方法,并且对功能进行增强。在装饰角色中通过构造方法传入真实角色。
装饰类的开发步骤:
  1. 装饰类继承于真实类,重写真实类需要增强的方法。
  2. 装饰类通过构造方法传入抽象对象到装饰类中
  3. 在被重写的方法中,先调用真实类中的同名方法,并且对方法的功能进行增强。

image


示范

##### 抽象角色:是一个接口或抽象类,定义真实角色具有哪些功能。

public interface Star {

    /**
     * 唱歌
     */
    void sing();

    /**
     * 跳舞
     */
    void dance();

}
真实角色:实现了抽象角色,并且实现了接口中所有的方法。
public class LingMeiMei implements Star {

    @Override
    public void sing() {
        System.out.println("林妹妹唱歌:萌萌站起来");
    }

    @Override
    public void dance() {
        System.out.println("林妹妹跳舞");
    }

}
装饰类继承于真实类
public class DecorationOne extends LingMeiMei {

    private Star star;

        this.star = star;
    }

    //重写真实类需要增强的方法
    @Override
    public void sing() {
        //调用它现有的功能
        star.sing();
        //调用前进行功能的增强
        System.out.println("鼓掌,献花");
    }
}
增强装饰类继承于真实对象
public class DecorationTwo extends LingMeiMei {
    private Star star;

    //构造方法传入抽象对象
    public DecorationTwo(Star star) {
        this.star = star;
    }

    //重写增强的方法
    @Override
    public void sing() {
        //调用真实对象的方法
        star.sing();
        System.out.println("给出场费");
    }

}
main 使用者
public class Fans {

    public static void main(String[] args) {
        //1. 实例化真实对象
        Star s1 = new LingMeiMei();
        //2. 创建装饰对象,传入了要增强的真实对象
        Star s2 = new DecorationOne(s1);
        //再次增强
        Star s3 = new DecorationTwo(s2);
        //3. 调用方法

        /*
        //调用的顺序不同,效果也不同
        Star s2 = new DecorationTwo(s1);
        Star s3 = new DecorationOne(s2);
        */
        s3.sing();
        //s1.dance();
    }

}

装饰者模式与代理模式的区别:

开发模式区别
装饰者模式注重的是对原有的功能的增强
代理模式注重的是对原有功能的拦截,甚至完全替换原有的功能

案例 通过过滤器解决POST和GET的编码问题

  • GET方式解码回顾
String 乱码 = request.getParameter("name")
new String("乱码".getBytes("iso-8859-1"),"utf-8")
思路

通过装饰类模式来给GET解决编码问题
1. POST方法很容易实现,GET方法因为需要得到每一项的参数进行编码,而且一开始并不知道有哪些参数。对request中getParameter()方法进行增强,让它直接对GET方法进行解码,到了Servlet中得到的汉字就不是乱码。

  1. 要继承的代理类是哪一个呢?查API文档可知,HttpServletRequest接口的实现类是HttpServletRequestWrapper
  2. 重写request.getParameter()方法,对这个方法进行装饰,在方法中实现编码的功能。
实现步骤:

装饰类:
1. 写一个类装饰角色MyRequestWrapper继承于真实角色HttpServletRequestWrapper,对它进行增强
1. 在类中声明一个成员变量HttpServletRequest,这是抽象角色
1. 通过构造方法转入HttpServletRequest的对象
1. 重写request.getParameter()方法,对汉字进行编码。

- 调用原来request.getParameter() 得到未编码前的字符串
- 判断如果是GET方法,而且值不为null,则进行编码。new String(“乱码”.getBytes(“iso-8859-1”),”utf-8”)
- 返回增强以后的字符串

过滤器:
1. 在过滤器中首先给POST方法编码
1. 创建装饰类对象MyRequestWrapper
1. 在过滤器中放行,注意:这里的过滤器放行的是装饰类的对象,而不应该是原来的request对象

这样就既能解决POST编码问题,也解决了GET编码问题

/**
 * 过滤所有Servlet中使用POST方法提交的汉字的编码
 * 
 * @author NewBoy
 * 
 */
public class EncodingFilter implements Filter {

    // 成员变量,通过配置属性参数设置的编码值(UTF-8)
    private String charset;

    @Override
    public void destroy() {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // 设置汉字的编码, charset相当于utf-8,解决了POST的编码问题
        request.setCharacterEncoding(charset);

        //直接实例化增强的装饰类,用于解决GET的编码问题
        MyRequest myRequest = new MyRequest((HttpServletRequest) request);

        // 放行,传递给下一个过滤链或web资源,放行的是增强以后的对象
        chain.doFilter(myRequest, response);
    }

    // 过滤的编码参数,通过filterConfig得到
    @Override
    public void init(FilterConfig config) throws ServletException {
        charset = config.getInitParameter("charset");
        System.out.println(charset);
    }


    /*
     * 抽象角色:接口HttpServletRequest 真实角色:HttpServletRequestWrapper
     * 实现了HttpServletRequest接口 装饰角色:我们的类 class MyRequest extends
     * HttpServletRequestWrapper重写getParameter()方法增强
     */
    private class MyRequest extends HttpServletRequestWrapper {

        private HttpServletRequest request;

        // 通过构造方法传入对象
        public MyRequest(HttpServletRequest request) {
            super(request);
            this.request = request;
        }

        // 重写getParameter方法进行功能的增强
        @Override
        public String getParameter(String name) {
            // 1. 得到原来的值
            String value = request.getParameter(name);
            // 2. 判断是否是GET方法,只有GET方法进行解码
            // 解码
            if (value == null) {
                return null;
            }
            // 不为空
            if ("GET".equals(request.getMethod())) {
                // 解码
                try {
                    return new String(value.getBytes("iso-8859-1"), charset);
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            }
            return value;
        }

    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值