需求:
能从File中读取字符串;
能从Buffer中读取字符串;
能把读取的字符串反转;
能把读取的字符串转为小写。
方案1:通过继承来解决

存在的问题:
1.类爆炸。如果再加入一个新的字符串处理,如小写转大写,有多少个数据源,就要增加多少个类;
2.如果字符串处理算法变化,或者读取数据的算法变化,需要修改多个类。
原因分析:
1.读取数据的算法,和字符串处理的算法,应该是相互独立的,可以独立的变化。上述方案把两个方法紧紧地绑定在一起。如果有M个读数据算法,有N个字符串处理算法,则需要M*N个类。这就是类爆炸。
2.读取数据的算法没有抽象出来,而是有多个拷贝,分散在各个类中。如果这个算法要改变,就要修改多个类。
方案2:

存在的问题:
1.所有的特征都放在了抽象层。即使用户不需要readReversedLine、readLowerCaseLine,也需要依赖于它们。
2.如果想增加新的字符串处理操作,需要修改抽象层InputStream,从而引起InputStream用户代码的变更。即,InputStream对于字符串处理操作的变更不是开放-关闭的。
方案3:通过组合来解决(Decorator模式)
读取数据是InputStream的核心职责,字符串处理是InputStream的附加职责。我们可以通过组合的方法,动态地为读取数据职责添加附加地字符串处理职责。

string
ReverseInputStream::readLine()
{
string result = m_cStream.readLine();
ReverseString(result);
return result;
}
总结:
1.作用:动态地给一个对象添加一些额外地指责。
2.优点:
可以动态地给对象添加职责,非常灵活,用户需要什么职责,就添加什么职责;
附加职责的变化,不会引起用户代码的变化,即开放-关闭。
3.缺点:
有很多小对象,如ReverseInputStream、LowerCaseInputStream等,增加了系统的复杂性。
4.适用性:
希望动态地、透明地给单个对象添加职责。添加职责的动作不影响该对象的用户;
对象有两种职责(核心职责、附加职责),如果用生成子类的方法进行扩充,会引起类爆炸。