摘要:前言关于设计模式,想必大家的第一感觉就是过于高深,有点虚吧。为什么要学习设计模式因为要装逼啊咳咳,大家请忽略前面那句话。处处都是设计模式的体现,所以若想攻下,设计模式是必学的。下节预告单例模式
前言
关于设计模式,想必大家的第一感觉就是过于高深,有点虚吧。相对来说,我们还是更熟悉ssh或者ssm之类的开发框架,一个工具用久了就会熟能生巧,就像刷漆工,时间长了也知道如何刷的一手漂亮的好墙。我们把springmvc用的很溜,把mybatis用的很溜,但这只是一个合格的程序员应该具备的能力之一。于是我们便成为了代码工人,想站在更高角度去设计,设计模式是必不可少的。简介
废话那么多,我们直接进入正题呢,到底什么是设计模式呢?我在设计模式之禅上摘抄出这一句话:
为什么要学习设计模式设计模式(Designpattern)是一套理论,由软件界的先辈们总结出的一套可以反复使用的经验,它可以提高代码的可重用性,增强系统的可维护性,以及解决一系列的复杂问题。
因为要装逼啊...咳咳,大家请忽略前面那句话。相信大家都有阅读spring源码的经历吧,看到类层次设计图,为什么会有这么多的接口,这么多的抽象类,这么多实现,心里有一万只草泥马狂奔而过。spring处处都是设计模式的体现,所以若想攻下spring,设计模式是必学的。其次,作为一个coder,最烦的就是需求变更,我们可以分析现有的需求,预测可能发生的变更,但是我们不能控制需求的变更。既然需求不可变更,那如何拥抱变化呢?设计模式给了我们知道,提出了6大原则,在此基础上提出了23种设计模式。如果你通晓了23种设计模式,那你就可以站在一个更高的层次去赏析程序代码,完成从代码工人到架构师的转变~>~.
设计模式六大原则 单一职责原则(最容易理解,最难实施的一个原则)描述:应该有且仅有一个原因引起类的变更 相信大家已经很不屑了,切,这么简单的东西还拿出来说。可是道理简单实现难啊。下面我给大家示例一些代码: public interface IUserInfo { void setUserName(String name); void setUserAge(int age); void walk(); void seeMovie(); void addRole(Role role); } 相信初级程序员都不会犯这样的错,将用户信息和用户行为放在同一个类里。最佳的做法就是将用户信息和用户行为分开管理,加角色动作也应该放在相应的实现类里。这是我临时想的例子,虽然很简单,但足以表达单一原则的意思。单一职责原则最难划分的就是职责,职责没有量化的标准,职责划分的过于细,类的数量会暴增,系统复杂度会以指数趋势增长,所以建议是接口一定要做到单一职责,累类设计尽量做到单一职责。里氏替换原则(使用时一定要注意子类的个性化..)
描述:所有引用基类的地方必须能透明地使用其子类的对象。 java与c++不同,java是一门单根继承的语言。使用extend关键字声明继承,若不使用,则代表继承Object。子类继承父类,会拥有父类的方法和属性,很多开源框架的扩展接口都是通过继承父类来完成的。通过这个特性,我们明白只要父类存在的地方,我们都可以替换成子类,并且编译器不会报错。但是java允许子类重写父类方法,这种子类的个性化有时会严重违背里氏替换原则.给大家上个示例:
public class AnyClazz{ //有某一个方法,使用了一个父类类型 public void someoneMethod(Parent parent){ parent.method(); } } public class Parent { public void method(){ System.out.println("parent method"); } } public class SubClass extends Parent{ //结果某一个子类重写了父类的方法,说不支持该操作了 public void method() { throw new Exception(); } } public class Test{ public static void main(String[] args) { AnyClazz anyClazz = new AnyClazz(); anyClazz.someoneMethod(new Parent()); anyClazz.someoneMethod(new SubClass()); } }
程序运行结果肯定会报错,这就相当于我们埋了一个雷,子类复写父类方法,编译期不报错,运行期就会报错。所以建议在项目中使用此原则时,应尽量避免子类的个性,一旦子类有个性,子类和父类的矛盾将可能直接破坏整个程序。
依赖倒置原则(很常见,现在的企业开发中业务层都有对应接口)描述:面向接口编程。 在Java中的语言表现就是:模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类发生的。接口和抽象类不依赖于实现类。实现类依赖接口或抽象类。简而言之,就是之前的描述~~。给大家举个例子:
public class Cooker { public void work(){ System.out.println("我会做饭"); } } public class Boss { public void recruitPerson (Cooker cooker){ cooker.work(); } } public class Test { public static void main(String[] args) { Boss boss = new Boss(); boss.recruitPerson(new Cooker()); } } 运行结果:我会做饭
上面代码一个大老板刚开了一个超市,在招厨师。假如我们要是招大堂经理怎么办?创建经理类,在boss中增加招经理的方法同时在test中修改。这样改好吗?仅仅是需求改了一点点,我们就要在所有代码里进行一些改动,这代价也太大了吧,耦合性忒高了~ 不要着急,依赖倒置原则可以帮我们解决这个问题,它可以减少类间的耦合性,提高系统的稳定性,降低并行开发引起的风险,提高代码可读性和维护性。修改之后的例子如下:
public interface IWorker { void work(); } public class Cooker implements IWorker { @Override public void work(){ System.out.println("我会做饭"); } } public class Manager implements IWorker { @Override public void work() { System.out.println("糊弄老板,指挥其他人干活"); } } public interface IBoss { void recruitPerson(IWorker iWorker); } public class Boss implements IBoss{ @Override public void recruitPerson(IWorker iWorker) { iWorker.work(); } } public class Test { public static void main(String[] args) { Boss boss = new Boss(); IWorker iWorker = new Manager(); boss.recruitPerson(iWorker); } } 运行结果: 糊弄老板,指挥其他人干活
咋一看,类变得更多了..使用技术总是要有点成本的吗,但假如以后我们在增加招理货员,招收银员等等改动就小了。其实这个原则的本质就是通过抽象是各个类和模块的实现独立,不互相影响,实现松耦合。接口隔离原则(六大原则中身材最好的那个小姐姐)
描述:接口尽量细化,同时接口中方法尽量少。 看到上面的描述可能会有点疑惑,这个和第一个的小姐姐(单一职责原则)有点像啊。单一职责衡量的是类的和接口职责要单一,对,是职责!而接口隔离原则就只是要求接口的粒度尽可能的小,最好就是一个接口一个方法(这是完美符合接口隔离原则的),不过这样做的话是明显要被其他小伙伴干死的(2333~~~)。接口粒度太小,接口数就会暴增,开发人员呛死在接口的海洋里,接口粒度太大,灵活性降低,无法提供定制服务。给大家举个例子:
//美食 public interface ICate { void goodLool(); void niceTaste(); void cleanFood(); } public class Cate implements ICate{ @Override public void goodLool() { System.out.println("色相看起来很好O(∩_∩)O哈哈~"); } @Override public void niceTaste() { System.out.println("吃起来,味绝了(*^▽^*)"); } @Override public void cleanFood() { System.out.println("食材很干净,食用放心"); } } public abstract class AbstractPerson { protected ICate iCate; public AbstractPerson(ICate iCate) { this.iCate = iCate; } abstract void eat(); } public class Person extends AbstractPerson { public Person(ICate iCate) { super(iCate); } @Override void eat() { iCate.cleanFood(); iCate.goodLool(); iCate.niceTaste(); } } public class Test { public static void main(String[] args) { ICate iCate = new Cate(); AbstractPerson abstractPerson = new Person(iCate); abstractPerson.eat(); } } 运行结果: 食材很干净,食用放心 色相看起来很好O(∩_∩)O哈哈~ 吃起来,味绝了(*^▽^*)
上面的例子我去吃美食,我对美食的标准是看起来,闻起来像,吃起来放心(吃货up!up!)。可是每个人对美食的标准都是一样的,你总不能因为臭豆腐闻起来很臭就不是美食吧。可是现在接口定义了只有三个条件都满足才能叫美食,这个该怎么办?难道要再扩展一个美食接口,只定义味道标准,可是我们的抽象类依赖的是ICate接口,我们的person又怎么只根据味道去分辨是不是美食呢?我们采用接口隔离原则去细化接口,示例如下:
public interface IGoodLookCate { void goodLook(); } public interface IGoodTasteCate { void niceTaste(); void cleanFood(); } public class Cate implements IGoodLookCate,IGoodTasteCate{ @Override public void goodLook() { System.out.println("色相看起来很好O(∩_∩)O哈哈~"); } @Override public void niceTaste() { System.out.println("吃起来,味绝了(*^▽^*)"); } @Override public void cleanFood() { System.out.println("食材很干净,食用放心"); } }
通过这样的重构后,不仅是要好吃的美食还是要好看的美食,都可以保持接口的稳定。当然你如果要说美食的标准又变了,接口还得改。没错,但是设计是有限度的,不能无限考虑未来,不然会陷入到过度设计的泥潭当中。迪米特法则(六大原则中最害羞的小姐姐)
描述:一个对象尽量不要知道太多关于其他对象的事
这个原则的核心观念就是类间解耦,低耦合。通俗一点来讲就是1.只和朋友交流2.朋友之间也是有距离的。举个例子说明下吧:
public class Goods { } public class Worker { public void sendGoods(Listlist){ System.out.println("送货喽:"+list); } } public class Boss { private static final List list = new ArrayList (); static { list.add(new Goods()); list.add(new Goods()); list.add(new Goods()); } public static void main(String[] args) { Worker worker = new Worker(); worker.sendGoods(list); } }
工人送货的场景,老板和工人是直接关系,工人和货物是直接关系,但是代码中老板和货物也搅在了一起,出现了过多依赖,破坏了老板类的健壮性,已经违反了迪米特法则。正确做法应该是将货物的逻辑抽取到工人当中(因为非常简单,就不上代码示例了)。朋友之间也是有距离的应当如何理解呢?假如类A提供了getA(),getB(),getC()三个方法,类B在逻辑内对ABC三个方法进行调用或者根据其返回值决定逻辑,这样也违反了迪米特法则,正确做法应是将对ABC三个方法调用的逻辑抽取封装到A中,同时将ABC三个方法进行私有化。
开闭原则(六大原则中当之无愧的大姐大)描述:对扩展开放,对修改关闭
开闭原则是六大原则里的精神领袖,也是最虚的原则。前面五个原则就是对开闭原则的具体解释。意思就是现在的系统中,不需要修改原有的代码,只需要扩展一些新的实现就可以搞定。但是没有任何一个系统可以做到,哪怕是spring也不可以,虽说他的扩展性已经强的{{BANNED}}。
以上6个原则是为了之后23种设计模式的描述,基本上都是我自己的理解,或许形容有好有差,不需要在意,各位完全可以有自己的理解。
下节预告:单例模式文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/68019.html
摘要:探究系统登录验证码的实现后端掘金验证码生成类手把手教程后端博客系统第一章掘金转眼间时间就从月份到现在的十一月份了。提供了与标准不同的工作方式我的后端书架后端掘金我的后端书架月前本书架主要针对后端开发与架构。 Spring Boot干货系列总纲 | 掘金技术征文 - 掘金原本地址:Spring Boot干货系列总纲博客地址:http://tengj.top/ 前言 博主16年认识Spin...
摘要:不知不觉写已经将近年时间了,在其中尝试着看了一下其它语言,发现其它语言都有很好的调试工具,协助调试和开发。难道就能依靠这样的断点调试么直到我发现了说来惭愧,这么久才发现,才发现是真心好用,于是花点时间总结一下,大致的内容框架如下 不知不觉写php已经将近5年时间了,在其中尝试着看了一下其它语言,发现其它语言都有很好的调试工具,协助调试和开发。难道php就能依靠var_dump 、ech...
摘要:我打算写一个链表操作的系列,来自的系列,实现语言是。通过自己实现一个链表和常用操作,可以加深理解这类数据结构的优缺点。链表经常用来训练指针操作,虽然这只对适用,但等高级语言中控制引用的思路其实也差不多。 TL;DR 我打算写一个链表操作的系列,来自 Codewars 的 Linked List 系列 kata ,实现语言是 JavaScript 。这篇是开篇,简单描述了一下我写这个的目...
摘要:系列文章更新计划列表主要对一些中常用的框架进行简单的介绍及快速上手,外加相关资料的收集更新列表会不定期的加入新的内容以进行扩充,如果你对此感兴趣可以站内联系我。 导读: 从第一次接触Spring Boot 至今已经有半年多了,在这期间也浏览了许多和Spring Boot 相关的书籍及文章,公司里面的许多项目也一直在使用Spring Boot。关于Spring Boot的一些看法:Spr...
阅读 1130·2021-11-16 11:45
阅读 967·2021-09-04 16:41
阅读 3035·2019-08-29 16:40
阅读 2761·2019-08-29 15:34
阅读 2623·2019-08-29 13:11
阅读 1711·2019-08-29 12:58
阅读 1692·2019-08-28 18:00
阅读 1747·2019-08-26 18:26