🥳🥳🥳 茫茫人海千千万万,感谢这一刻你看到了我的文章,感谢观赏,大家好呀,我是最爱吃鱼罐头,大家可以叫鱼罐头呦~🥳🥳🥳
从今天开始,将开启一个专栏,
【贯穿设计模式】
,设计模式是对软件设计中普遍存在(反复出现)的各种问题,所提出的解决方案,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。为了能更好的设计出优雅的代码,为了能更好的提升自己的编程水准,为了能够更好的理解诸多技术的底层源码, 设计模式就是基石,万丈高楼平地起,一砖一瓦皆根基。 ✨✨欢迎订阅本专栏✨✨
🥺 本人不才,如果文章知识点有缺漏、错误的地方 🧐,也欢迎各位人才们评论批评指正!和大家一起学习,一起进步! 👀
❤️ 愿自己还有你在未来的日子,保持学习,保持进步,保持热爱,奔赴山海! ❤️
💬 最后,希望我的这篇文章能对你的有所帮助! 🍊 点赞 👍 收藏 ⭐留言 📝 都是我最大的动力!
🔥【贯穿设计模式】第一话·设计模式初介绍和单一职责原则🔥
在第一篇文章中,我们了解设计模式有七大原则,是我们在学习设计模式的基础,我们也学习到了第一个原则:单一职责原则;
我们来回顾下,它的定义:指对一个类来说,应当只有一个引起它变化的原因,否则类应该被拆分,即一个类应该只有一个职责。
并且我们通过学生上课的例子讲解并认识到各个阶段的代码所遇到的问题,也有优缺点,所以在应用单一职责原则时,只有逻辑足够简单,才可以在代码级别上违反单一职责原则;只有类中方法数量足够少,才可以在方法级别上违反单一职责原则。
今天我们要学习的是开闭原则,对扩展开放,对修改关闭。
开闭原则是编程中最基础最重要的设计原则,如果遵循开闭原则将有以下优点 :
遥想当初上学时期,甚至在高中的时候,每天的时间都会被大量的习题集,试卷,课后作业占据,除了刷题,就是刷题了,似乎只要刷多了,你就会了。哈哈这里就不细讲当初刷题的苦逼日子了。接下来就以这些习题集等例子来讲解开闭原则吧。
整个习题集的类图如图所示:
1. 习题接口:IExercise:
package com.ygt.principle.ocp; /** * 习题接口,主要有价格和姓名 */ public interface IExercise { Double getPrice(); String getName(); }
2. 高中习题类实现了习题接口:HighExercise:
package com.ygt.principle.ocp; /** * 高中习题类 */ public class HighExercise implements IExercise { // 习题价格 private Double price; // 习题名字 private String name; // 构造方法 public HighExercise(Double price, String name) { this.price = price; this.name = name; } public Double getPrice() { return this.price; } public String getName() { return this.name; } }
3. 习题集店贩卖习题:ExerciseStore:
package com.ygt.principle.ocp; import java.util.ArrayList; import java.util.List; /** * 习题店 专门卖习题集的 */ public class ExerciseStore { // 习题店中包含各种习题集 private List<IExercise> exerciseList = new ArrayList<>(); // 初始化习题集 public ExerciseStore() { exerciseList.add(new HighExercise(63d, "五年高考三年模拟数学")); exerciseList.add(new HighExercise(53d, "五年高考三年模拟语文")); exerciseList.add(new HighExercise(43d, "五年高考三年模拟英语")); } // 展示习题集方法 public void showExercise() { System.out.println("~~~~~~~~~~~~~~本店拥有的高中习题集~~~~~~~~~~~~~~~"); System.out.println("习题名\t\t\t\t\t价格\t\t"); exerciseList.forEach(e-> System.out.println(e.getName() + "\t\t¥" + e.getPrice() + "元\t\t")); } // 测试调用习题集 public static void main(String[] args) { ExerciseStore store = new ExerciseStore(); store.showExercise(); } }
4. 演示结果:
~~~~~~~~~~~~~~本店拥有的高中习题集~~~~~~~~~~~~~~~ 习题名 价格 五年高考三年模拟数学 ¥63.0元 五年高考三年模拟语文 ¥53.0元 五年高考三年模拟英语 ¥43.0元
按照上面的写法,我们可以轻松写出习题店售卖习题集的过程,但是习题店每逢寒暑假的时候,为了让广大学子都能做上习题,习题店决定按照8.5折的强大优惠力度促进销售习题,而这时候就需要对现有的售卖习题的过程进行修改。如果按照原先的思路的话,就会直接在HighExercise类上,直接将价格修改。
package com.ygt.principle.ocp; public class HighExercise implements IExercise { // ....省略其他代码 public Double getPrice() { return this.price * 0.85; } }
下面就一起来探讨下解决方法吧。
如果直接修改原先的习题类的话,就会导致不是遵循了开闭原则了,违反了对修改关闭的原则,所以此时不能直接修改HighExercise类或者是IExercise接口了。而是通过扩展一个类来完成该修改价格的需求。
增加一个子类DiscountHighExercise继承HighExercise类来完成:
注意上面修改的HighExercise类中的getPrice()方法应该恢复原先。
package com.ygt.principle.ocp; public class DiscountHighExercise extends HighExercise{ public DiscountHighExercise(Double price, String name) { super(price, name); } // 重写获取价格方法 @Override public Double getPrice() { // 增加价格为原来的85折。 return super.getPrice() * 0.85; } }
再稍微修改下ExerciseStore类即可:
package com.ygt.principle.ocp; import java.util.ArrayList; import java.util.List; /** * 习题店 专门卖习题集的 */ public class ExerciseStore { // 习题店中包含各种习题集 private List<IExercise> exerciseList = new ArrayList<>(); // 初始化习题集 public ExerciseStore() { // 修改地方,将创建类改成DiscountHighExercise exerciseList.add(new DiscountHighExercise(63d, "五年高考三年模拟数学")); exerciseList.add(new DiscountHighExercise(53d, "五年高考三年模拟语文")); exerciseList.add(new DiscountHighExercise(43d, "五年高考三年模拟英语")); } // 展示习题集方法 public void showExercise() { System.out.println("~~~~~~~~~~~~~~本店拥有的高中习题集~~~~~~~~~~~~~~~"); System.out.println("习题名\t\t\t\t\t价格\t\t"); exerciseList.forEach(e-> System.out.println(e.getName() + "\t\t¥" + e.getPrice() + "元\t\t")); } // 测试调用习题集 public static void main(String[] args) { ExerciseStore store = new ExerciseStore(); store.showExercise(); } }
再看下执行结果:
~~~~~~~~~~~~~~本店拥有的高中习题集~~~~~~~~~~~~~~~ 习题名 价格 五年高考三年模拟数学 ¥53.55元 五年高考三年模拟语文 ¥45.05元 五年高考三年模拟英语 ¥36.55元
这样通过增加一个DiscountHighExercise类,修改ExerciseStore中少量的代码,就可以实现习题集价格的85折的需求啦,而其他部分没有任何变动,体现了开闭原则的应用。
注意的一点:开闭原则是对扩展开放,对修改关闭,但这并不意味着不做任何修改,低层模块的变更,必然要有高层模块进行耦合,否则就是一个孤立无意义的代码片段。
相信各位看官看到这里大致都对设计模式中的其中一个原则有了了解吧,开闭原则实际上的定义就是扩展开放,对修改关闭,提高软件系统的可复用性及可维护性。
学好设计模式,让你感受一些机械化代码之外的程序设计魅力,也可以让你理解各个框架底层的实现原理。最后,祝大家跟自己能在程序员这条越走越远呀,祝大家人均架构师,我也在努力。 接下来期待第三话:依赖倒转原则。 💪💪💪
文章的最后来个小小的思维导图:
🧐 本人不才,如有什么缺漏、错误的地方,也欢迎各位人才们评论批评指正!🤞🤞🤞
🤩 当然如果这篇文章确定对你有点小小帮助的话,也请亲切可爱的人才们给个点赞、收藏下吧,非常感谢!🤗🤗🤗
🥂 虽然这篇文章完结了,但是我还在,永不完结。我会努力保持写文章。来日方长,何惧车遥马慢!✨✨✨
💟 感谢各位看到这里!愿你韶华不负,青春无悔!让我们一起加油吧! 🌼🌼🌼
💖 学到这里,今天的世界打烊了,晚安!🌙🌙🌙