您的位置:首页 > 移动开发 > Android开发

Android装饰者模式学习笔记(2)

2017-11-14 17:42 183 查看

Android装饰者模式学习笔记(2)

Android装饰者模式学习笔记(1)

1接着上一篇来,先说疑问1

我们这么做只能实现AXXX模式,假如我想实现XXXX模式怎么做,例如DCBA?A类一定要作为最后收尾的类吗,如果不是,该怎么改?

其实我们上一篇说必须用A来收尾,是因为A是无参构造函数,而BCD都需要一个参数,所以如果想改成输出DCBA,我们需要把A加一个带参构造函数,这个没问题(加构造函数没问题,但是代码逻辑会出问题,因为A没继承Decorate类)

但是,我们还需要把BCD加一个无参构造函数,但因为BCD的父类Decorate是带参构造函数,所以BCD无法添加无参构造函数

而如果我们把Decorate的带参构造函数拿掉,。。。。那代码就乱了,也就不是装饰者模式了吧

所以我个人认为:在这个情景里,装饰者模式只能做到AXXX模式而无法做到XXXX模式,即A类一定要作为收尾的类(如有不同意见欢迎回复)

疑问2

A类是不是被装饰者,如果不是,到底谁是被装饰者?

我个人认为A类是被装饰者,因为像我考虑疑问1一样,A不是Decorate的子类,无法通过写带参构造函数的方式来让A像BCD一样可以接受同类型的变量,A只能用来收尾,所以A是被装饰者

疑问3

装饰者类BCD,如果不重写output方法,代码也不会报错,因为他们的父类已经重写过了,那执行结果会是什么呢,为什么呢?

先看我们最初的写法

Decorate decorate = new D(new C(new B(new A())));
System.out.println(decorate.outPut());


结果是ABCD

现在我把B类的output方法屏蔽掉

public class B extends Decorate {//这里通过继承Decorate类,而Decorate类实现I接口来间接完成B实现I接口

public B(I i) {//因为父类构造函数带参,所以这里也得写
super(i);
}

//    @Override
//    public String outPut() {//这个如果不重写,会有什么影响,代码的执行情况是什么样的,后续研究
//        return i.outPut() + "B";
//    }
}


结果是ACD

为什么是ADC呢,我们还是看Decorate decorate = new D(new C(new B(new A())));

(1)肯定是先执行A的output,输出一个A

(2)然后执行B的output,但是B没重写,所以肯定执行的是父类的output方法,

父类的output方法写的是return i.outPut();

这个i是谁,我觉得就应该是B的参数,B的参数是A,也就是A.output,

所以又输出了一遍A(这里是又输出了一遍而不是又输出了一个,所以到目前为止还是A,而不是AA,这里我想了略长时间)(这里有点只可意会不可言传的感觉,但我已经尽量描述的准确了)

(3)然后执行C的output,也就是之前的A + C

(4)D也同理

所以结论就是如果不重写扩展方法,那么就会在执行一遍 被装饰者的方法(如有不同意见欢迎回复)

疑问4

可不可以不创建装饰者父类,仅依靠BCD实现I接口能不能完成扩展呢?

能完成扩展,但是应该就不符合装饰者模式了,先看改变后的代码,BCD还是之前的三个类,我把代码放到一个代码块里了

public class B implements I {

I i;

public B(I i) {
this.i = i;
}

@Override
public String outPut() {
return i.outPut() + "B";
}
}
public class C implements I {

I i;

public C(I i) {
this.i = i;
}

@Override
public String outPut() {
return i.outPut() + "C";
}
}
public class D implements I{

I i;

public D(I i) {
this.i = i;
}

@Override
public String outPut() {
return i.outPut() + "D";
}
}


public class Test {

public static void main(String[] args) {

I decorate = new D(new C(new B(new A())));//只是这里把之前的Decorate类换成了I类型
System.out.println(decorate.outPut());
}

}


输出结果依然是ABCD, 但是没了装饰者父类之后,出现了几个问题

1代码重复了,每个子类都要定义一个I i,变得麻烦了

2如果我在想扩展新功能,比如输出“1234”,由于没有父类,扩展起来相对麻烦,而且也犯了1的错误

3不符合装饰者模式

所以还是写一个装饰者父类比较好,这就是关于上一篇博客留下的疑问的思考,全是个人理解,如有不对,欢迎在评论里讨论。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: