导语:
进入点融网近半年,第一次提笔写作,之前由于点融大神众多,不敢轻易妄言,恐贻笑大方;思前想后,还是从基础谈起,追求通俗易懂,简单实用为主
说到设计模式,对于年长点的Java工程师一定觉得过于基础简单,23种设计模式必定了然于心;既然如此基础的东西,笔者为何还要拿出来累述,说起原因,要从之前的几次面试说起。
由于部门需要招聘Java工程师,笔者曾经面试过几位年轻的应聘者,面试过程中,问及知晓精通哪些设计模式,通常只能说出3,4种,让其书写简单样例,也是写的漏洞百出,问到各种设计模式的应用场景,更是不知;由此可见,设计模式的重要性已经被很多java工程师所忽视。故此,笔者收集各方资料,并融入自己多年编程经验和心得体会,并结合简单生动的例子,深度解读设计模式。
1设计模式的分类
设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。
设计模式的分类
总体来说设计模式分为三大类:
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
其实还有两类:并发型模式和线程池模式。用一个图片来整体描述一下:
2设计模式的六大原则
1、开闭原则(Open Close Principle)
开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类,后面的具体设计中我们会提到这点。
2、里氏代换原则(Liskov Substitution Principle)
里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。 LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现 抽象化的具体步骤的规范。—— From Baidu 百科
3、依赖倒转原则(Dependence Inversion Principle)
这个是开闭原则的基础,具体内容:针对接口编程,依赖于抽象而不依赖于具体。
4、接口隔离原则(Interface Segregation Principle)
这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。还是一个降低类之间的耦合度的意思,从这儿我们看出,其实设计模式就是一个软件的设计思想,从大型软件架构出发,为了升级和维护方便。所以上文中多次出现:降低依赖,降低耦合。
5、迪米特法则(最少知道原则)(Demeter Principle)
为什么叫最少知道原则,就是说:一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。
6、合成复用原则(Composite Reuse Principle)
原则是尽量使用合成/聚合的方式,而不是使用继承。
3模板方法模式
读者一定会好奇,如此多的设计模式,笔者为何要从模板模式开始,而不是最基础的单例模式或者工厂模式,理由其实很简单,因为在点融的代码里可以看到大量的模板模式,众多的Transaction处理,及第三方支付,其实都用到了模板方法模式,而且我们熟知的Spring事物管理也用到了模板方法模式。
言归正传,接下来笔者会结合一个简单的例子,来解读模板方法模式;
我们以泡茶和冲咖啡为例,设计一段小程序;
咖啡冲泡法
(1)把水煮沸
(2)用沸水冲泡咖啡
(3)把咖啡倒进杯子
(4)加糖和牛奶
茶冲泡法
(1)把水煮沸
(2)用沸水浸泡茶叶
(3)把茶倒进杯子
(4)加柠檬
接下来我们快速搞定咖啡和茶的类:
咖啡的实现....
接下来是茶....
我们发现了重复的代码,这是好现象,这表示我们需要清理一下设计了,既然咖啡和茶如此的相似,我们可以将共同点抽取出来,放进一个基类里。
第一版的抽象:
可以看到,咖啡和茶特有的方法放在子类中,每个子类都覆盖了prepareRecipe()方法,并实现了自己的冲泡方法。
新的设计看似封装了咖啡和茶的共同点,我们是不是忽略了某些其他的共同点?
更进一步的设计
注意两份冲泡法都采用了相同的算法:
(1)把水煮沸
(2)用沸水泡咖啡或茶
(3)把饮料倒进杯子
(4)在饮料中加入适当的调料
接下来,我们将prepareRecipe()也抽象化
最后我们重新处理咖啡和茶类,这两个类现在都是依赖超类来处理冲泡法,所以只需要自行处理冲泡和添加调料部分:
我们刚刚实现的就是模板方法方式,模板方法定义了一个算法的步骤,并允许子类为一个或多个步骤提供实现。
接下来,我们对模板方法进行挂钩
钩子是一种被声明在抽象类中的方法,但只有空的或者默认的实现。钩子的存在,可以让子类有能力对算法的不同点进行挂钩。要不要挂钩,由子类自行决定。
我们对父类稍加改造:
为了使用钩子,我们在子类中覆盖它,在下面的例子中,钩子控制了咖啡饮料是否添加调料
接下来我们测试一下这个例子,用来制造热茶和热咖啡。
执行结果......
这个例子很不赖吧!
引入一个设计原则:
好莱坞原则:别调用我们,我们会调用你。
好莱坞原则可以给我们一种防止"依赖腐败"的方法。当高层组件依赖低层组件,而低层组件又依赖高层组件,而高层组件又依赖边侧组件,而边侧组件又依赖低层组件时,依赖腐败就发生了。在这种情况下,没有人可以轻易地搞懂系统是如何设计的。
在好莱坞原则下,我们允许低层组件将自己挂钩到系统上,但是高层组件会决定什么时候和怎样使用这些低层组件。换句话说,高层组件对待低层组件的方式是别调用我们,我们会调用你。
总结要点:
“模板方法”定义了算法的步骤,把这些步骤的实现延迟到子类。
模板方法模式为我们提供了一种代码复用的重要技巧。
模板方法的抽象类可以定义具体方法、抽象方法和钩子。
抽象方法由子类实现。
钩子是一种方法,它在抽象类中不做事,或者只做默认的事情,子类可以选择要不要去覆盖它。
为了防止子类改变模板方法中的算法,可以将模板方法声明为final。
好莱坞原则告诉我们,将决策权放在高层模板中,以便决定如何以及何时调用低层模块。
模板方法就先说到这里,下次笔者会带来别的设计模式。
本文作者:赵建涛(点融黑帮),现任点融Fin-Tech高级研发工程师,具备多年ERP云服务设计开发经验。
随着点融网新一轮融资,点融网即将开始大规模的扩张,需要各种优秀人才的加入,如果你觉得自己够优秀,欢迎加入我们!获取更多职位信息,请关注点融黑帮。
本文暂时没有评论,来添加一个吧(●'◡'●)