浅谈设计模式的学习(下)
时间过得真快啊,不知不觉又要周末了,借这个周末时间。把《浅谈设计模式的学习(下)》补上吧。
在《浅谈设计模式的学习(中)》中,说到了保持抽象的思维。接下来说一下第四点,做一个分享,也记录一下自己的学习历程。
4、学习设计模式,就不要把它看的太认真
设计模式是一个编程思想,它不是具体的代码套路。举个例子说明一下:
由于家传,接触到了一些中国的传统武术。当我与那些不懂传统武术的人交流的时候,他们总是认为中国的传统武术都是些套路、花架子,只是用来好看。在他们认为,两人打架,别人出拳又不是按照你的固定套路来,所以那些武术套路肯定没法用来实战。其实是怎么样呢?我想说他们太不了解中国传统武术了。其实传统武术不止套路,套路只是传统武术的一个练习身体协调等能力的辅助。其主要还是在思想。比如说,一动而无不动,就是让你调动全身动力来进行防御反击。学习传统武术就是把那些技击思想练到身上(当然,本人只是偶尔练练,还没那本事)。设计模式也是,它是一个在某些场景下的编程思想,或者说是思路。并不是固定套路。开发场景是多样的,这就要求你根据一定的思想合理的设计代码的结构。而不是一定要跟书上介绍的设计模式的代码结构一模一样。设计模式是思想层的东西,是抽象的,所以不用怕,它允许你多变灵活的使用,合理即可。不要把它看的太认真(不知道有没有人也跟我当初那样,认为必须写一个什么接口,然后怎么继承怎么组合调用才算是正确的设计模式)
好像无论怎么说,都显得很抽象。那就再来一个例子,用来跟上一遍文章中的那个责任链模式做一下比较来说明:
场景:模仿网络模型,数据包先经过tcp加上协议头后,再经过http加上http协议头后最后通过网络传输给对方。
第一步:几乎所有的设计模式都需要抽象出接口或者抽象类的,所以我们抽象出一个产生数据包的接口
1 public interface IPackageCreator { 2 3 public String createPackage(); 4 }
第二步:我们简单地写一个实现IPackageCreator接口的具体产生消息体的类:
1 public class PackageBodyCreator implements IPackageCreator { 2 3 @Override 4 public String createPackage() { 5 6 return "大家好"; 7 } 8 9 }
第三步:我们要在产生的消息体上加tcp协议头,还要再加http协议头。考虑添加的协议头可能随时变化,比如说还需要再包装一个什么其他的协议头。我们就用装饰模式来一个个装饰。即使后边需求变了,我们也可以自由组合达到我们想要的功能。所有的装饰者都需要有一个具体的装饰对象,所以我们把此对象抽取到一个抽象装饰者类中。由于装饰者类是对被装饰者类的功能加强,不应该让客户端调用时感觉到装饰前后的差异,所以此抽象类实现了IPackageCreator接口:
1 public abstract class AbstractDecorator implements IPackageCreator { 2 3 protected IPackageCreator creator; 4 5 public AbstractDecorator(IPackageCreator c){ 6 this.creator = c; 7 } 8 9 }
第四步:现在我们可以写具体的装饰者类了,这是用来添加tpc协议头和http协议头的两个装饰着类:
1 public class PackageTcpCreator extends AbstractDecorator { 2 3 public PackageTcpCreator(IPackageCreator c) { 4 super(c); 5 } 6 7 @Override 8 public String createPackage() { 9 10 return "tcp协议头:"+this.creator.createPackage(); 11 } 12 13 }
1 public class PackageHttpCreator extends AbstractDecorator{ 2 3 public PackageHttpCreator(IPackageCreator c) { 4 super(c); 5 } 6 7 @Override 8 public String createPackage() { 9 10 return "http协议头:"+this.creator.createPackage(); 11 } 12 13 }
第五步:接下来看一下客户端代码的编写:
1 public class Main { 2 3 public static void main(String[] args) { 4 IPackageCreator creator = new PackageBodyCreator(); 5 IPackageCreator tcpDecorater= new PackageTcpCreator(creator); 6 IPackageCreator httpDecorater = new PackageHttpCreator(tcpDecorater); 7 System.out.println(httpDecorater.createPackage()); 8 } 9 10 }
整个代码写完了。这种模式有没有很熟悉的感觉啊,就跟inputstream套了一层BufferedInputStream,然后再套一层DateInputStream差不多吧。都是装饰者模式嘛。但是跟《浅谈设计模式的学习(中)》中的责任链模式比一下呢。都有一条链对吧,而且都有接口、抽象类和具体实现。会不会有点混乱呢。可能会有点吧,怎么个个设计模式都有接口、继承抽象类啊,很多也会是一个对象有一个另一个接口的引用属性。这就因为设计模式的目标就是为了方便扩展。为了扩展自然就需要依赖抽象而不是具体对象了。所以很多设计模式都有接口、继承等关系很正常。如果我们在学习设计模式时,刻意记住创建一个什么样的接口,如何去继承去实现。那么我们会被他们大部分的相似性搞混。对于以上说的责任链模式和装饰模式,我们只需要理解:装饰模式是对已对象功能的增强;责任链模式是按一个链条一次处理任务。具体怎么应用你还得需要根据应用场景灵活多变。
5、学习设计模式,多读开源代码最有效
设计模式本来就是抽象的,学习最好的方式就是例子。虽然讲设计模式的书中举得例子也不少,但例子大都比较“单纯”(没有实际应用场景需要考虑的问题多)。所以学习读那些优秀的开源代码是你快速掌握和灵活应用设计模式的最快的方法了。也许刚开始读源代码是一个痛苦的过程。但当你开始了慢慢的就能找到一些规律,也就变得容易。万事开头难。两周后的今天你肯定比现在开始的你更优秀!