装饰者模式总结

装饰者模式

装饰者设计模式和适配器模式有点类似,算得上是适配器的一种特殊形式。个人浅显的理解,只是认为两者在某一种程度上有着细微的差别,后面会做一个对比。这里采用一个较为通俗的例子,常用的登录模式来介绍装饰者模式。

传统的登录方式就是就是根据用户名和密码进行登录,如果需要提供第三方登录方式,就需要在原有的项目上进行扩展,而这里的扩展,就需要用到装饰者模式

类图结构如下:



这里是在原有的注册登录方式进行扩展,ISigninService是原有的登录方式,SigninServiceImpl是原有登录方式的实现,下面给出代码

public interface ISigninService {

    public ResultMsg regist(String username, String password);

    public ResultMsg login(String username, String password);

}
public class SigninServiceImpl implements ISigninService{
    @Override
    public ResultMsg regist(String username, String password) {
        return null;
    }

    @Override
    public ResultMsg login(String username, String password) {
        return null;
    }
}

ISinginForThirdService是提供第三方登录方式的接口,该接口继承了被装饰者的接口,然后在其上面进行了扩展

public interface ISigninForThirdService extends ISigninService{
    public ResultMsg loginForQQ(String id);

    public ResultMsg loginForWeChat(String id);

    public ResultMsg loginForToken(String id);

    public ResultMsg loginForTelephone(String telephone,String code);

    public ResultMsg loginForRegist(String username, String password);
}

其对应的实现类

public class SigninForThirdService implements ISigninForThirdService{

    private ISigninService signinService;

    public SigninForThirdService(ISigninService signinService){
        this.signinService = signinService;
    }

    /**
     * 不需要修改的,就直接调用原来的
     * @param username
     * @param password
     * @return
     */
    @Override
    public ResultMsg regist(String username, String password) {
        return signinService.regist(username,password);
    }

    /**
     * 如果针对原来的方法,有修改的,这里也可以直接覆盖
     * @param username
     * @param password
     * @return
     */
    @Override
    public ResultMsg login(String username, String password) {
        System.out.println("传统方式登录");
        return signinService.login(username,password);
    }

    public ResultMsg loginForQQ(String id){
        System.out.println("利用QQ进行登录");
        return loginForRegist(id,"QQ_EMPTY");
    }

    public ResultMsg loginForWeChat(String id){
        System.out.println("利用微信进行登录");
        return null;
    }

    public ResultMsg loginForToken(String id){
        System.out.println("利用标示进行登录");
        return null;
    }

    public ResultMsg loginForTelephone(String telephone,String code){
        System.out.println("利用手机号进行登录");
        return null;
    }

    public ResultMsg loginForRegist(String username,String password){
        this.regist(username,"password");
        ResultMsg resultMsg=this.login(username,"QQ_EMPTY");
        return resultMsg;
    }
}

简单的测试类

public class SigninTest {

    public static void main(String[] args) {
        //原来的功能依旧会对外开放,新的功能同样也可以用
        //适配器中的方法,通常会打上过时的标签
        ISigninForThirdService signinForService = new SigninForThirdService(new SigninServiceImpl());
        signinForService.loginForQQ("testId");
    }

}

装饰者模式中,其实对于被装饰者,无需要知道装饰对象的存在,装饰对象中如果需要使用被装饰对象中的方法,可以维护一个被装饰者的引用,如果单纯的是对被装饰者的方法进行增强操作,可以不用维护引用,直接覆盖掉被装饰对象中的方法即可,这也是其不同于适配器模式的地方,适配器模式中,需要通过某种方式维护被装饰者的引用。总体来说,装饰者模式中,装饰对象与被装饰者是一个is-a的关系,而适配器模式中,似乎是has-a的关系。一定层度上来说,装饰者模式好像就是多继承的一种实现而已

补充:

针对装饰者模式和适配器模式两者的区别,可以参考这篇博客——装饰者模式、适配器模式、代理模式的异同

针对装饰者模式更加深层次的理解,可以参考这篇博客,其中还对装饰者模式在IO中的应用有了介绍(实例有点绕)——深入理解装饰者模式

猜你喜欢

转载自blog.csdn.net/liman65727/article/details/79740534
今日推荐