提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、七大原则
    • 1、开闭原则
    • 2、单一职责原则
    • 3、接口隔离原则
    • 4、依赖倒转原则
    • 5、里氏替换原则
    • 6、合成复用原则
    • 7、迪米特法则
  • 总结

前言

设计模式,对于刚入门的程序员来说几乎和JVM是一个级别的,总觉得遥不可及。也觉得目前这个阶段没必要研究这样的知识。这种思想是错误的,不管你是刚入门的小白还是知识渊博的大牛,甚至其他行业的都可以学习设计模式,它不仅仅能应用于软件工程,也能应用于生活中的方方面面设计。起初设计模式是被应用于建筑领域的设计中,后来才慢慢引用于软件设计领域。
软件设计模式,是对软件设计中普遍存在(反复出现)的各种问题,所提出来的解决方案。但是它不仅仅局限于是方案,更是编码的规范以及思维。毫不夸张的说,它也是历代程序员代码设计经验的总结。其目的为了提高代码的可重用性、代码的可读性以及代码的可靠性

我们不要做码农,要做有思维、有灵魂的软件工程师。


一、七大原则

使用23种设计模式的基础就是遵守七大原则,下文会逐个介绍。另外由于时间精力有限,23种设计模式不会逐个研究,只会介绍15种常用的、重要的设计模式。初中级开发,能掌握个15种设计模式,应该差不多了。当然,掌握越多越好。

1、开闭原则

开闭原则是编程种最基础也是最重要的设计原则,其他六种原则其实最终就是为了实现开闭原则。
官方解释:软件实体应当对扩展开放,对修改关闭。

一个软件实体如类、模块或函数应该对扩展开放,对修改关闭,用抽象构建框架,用实现扩展细节,当软件需要变化是,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码类实现改变。

开闭原则是面向对象程序设计的终极目标,它使软件实体拥有一定的适应性和灵活性的同时具备稳定性和延续性。

黄金法则:当问到什么设计模式或者七大原则有啥优点的时候,记住 耦合性,内聚性,可维护性、可读性、可扩展性、重用性、灵活性等多方面去思考解答。

2、单一职责原则

官方解释:就一个类而言,应该仅有一个引起它变化的原因,应该只有一个职责

皇家翻译:就一个后台开发人员而言,应该仅有后台出问题这一个原因才能使他加班,前端炸了或者运维方面出问题了,他照样下班。分工明确,后台开发只负责后台开发职责。
如果不遵守单一职责原则,那么代码的耦合性很高,内聚性低。

优点:降低类的复杂性,提高类的可读性以及可维护性。

3、接口隔离原则

官方定义:客户端不应该被迫依赖于它不使用的方法,一个类对另一个类的依赖应该建立在最小的接口上。

当普通类实现一个接口时, 重写其下所有方法,这些方法真的有必要一一重写吗?如果不需要每个方法都重写,那么应该考虑把这个接口拆分成多个小接口,实行接口隔离原则。
优点:降低系统耦合性,提高内聚性、灵活性以及可维护性。当类实现接口时,可避免一些被迫实现一些与该类无关的代码,这和前面的单一原则有些类似,都是为了提高类的内聚性,降低他们之间的耦合性。但是单一职责注重的是类的职责,而接口隔离原则注重的对接口依赖的隔离。
上段代码理解理解,很简单代码,但需要仔细看。

package com.principle;public class Segregation {public static void main(String[] args) {//某粉丝 要看cxk跳、唱、篮球,不看rap和演戏Fans fans=new Fans();fans.useMoneyLookSing(new CXK());fans.useMoneyLookDance(new CXK());fans.useMoneyLookPalyBasketball(new CXK());
//某王老五 要看LH看rap、跳、演戏,不看唱、篮球WLW wlw = new WLW();wlw.useMoneyLookActing(new LH());wlw.useMoneyLookRap(new LH());wlw.useMoneyLookDance(new LH());}}//假设这是一个公共接口 实现了五个方法 唱、跳、rap、打篮球、演戏
interface showTime{void sing();void dance();void rap();void basketball();void acting();
}//CXK类实现了技能接口
class  CXK implements showTime{@Overridepublic void sing() { System.out.println("坤坤唱歌"); }@Overridepublic void dance() { System.out.println("坤坤跳舞"); }@Overridepublic void rap() { System.out.println("坤坤rap"); }@Overridepublic void basketball() { System.out.println("坤坤杂技篮球"); }@Overridepublic void acting() { System.out.println("坤坤演戏"); }
}
//LH类实现了公共接口
class  LH implements showTime{@Overridepublic void sing() { System.out.println("鹿鹿唱歌"); }@Overridepublic void dance() { System.out.println("鹿鹿跳舞"); }@Overridepublic void rap() { System.out.println("鹿鹿rap"); }@Overridepublic void basketball() { System.out.println("鹿鹿杂技篮球"); }@Overridepublic void acting() { System.out.println("鹿鹿演戏"); }
}//某粉丝 要看cxk跳、唱、篮球,不看rap和演戏
class Fans {public void useMoneyLookSing(showTime i){i.sing();}public void useMoneyLookDance(showTime i){i.dance();}public void useMoneyLookPalyBasketball(showTime i){i.basketball();}}//某王老五 要看LH看rap、跳、演戏,不看唱、篮球
class WLW {public void useMoneyLookDance(showTime i){i.dance();}public void useMoneyLookRap(showTime i){i.rap();}public void useMoneyLookActing(showTime i){i.acting();}
}

以上代码,在王老五或者粉丝花钱要看娱乐时,俩个实现类都实现了showtime这个接口下的所有方法,但是这俩个实现类并不是都能实现唱跳rap打篮球以及演戏,这是典型的违反了接口隔离原则的代码。所以解决方案是把接口细粒化,可以拆成多个接口,需要用到哪些技能就继承哪个接口,很简单,就不多写了,以免律师函警告。

4、依赖倒转原则

官方解释:
高层模块不应该依赖低层模块,两者都应该依赖其抽象;
抽象不应该依赖细节,细节应该依赖抽象
其核心思想是:要面向接口编程,不要面向实现编程。
依赖倒置原则是实现开闭原则的重要途径之一,它降低了客户与实现模块之间的耦合。
对于这些官方术语, 乍一看是懵的。但是你仔细一看就会发现,还不如乍一看。
直接上代码

package com.principle;public class DependencyReverse {public static void main(String[] args) {Person person = new Person();person.eat(new Meat());person.eat(new Fruits());}}
//定义食物接口
interface IFood {public String eat();
}
//茶
class Fruits implements IFood {public String eat() {return "水果";}
}
//汤
class soup implements IFood {public String eat() {return "汤";}
}
//肉
class Meat implements IFood {public String eat() {return "肉";}
}class Person {//依赖倒置  面向接口编程 写法public void eat(IFood food ) {System.out.println(food.eat());}//普通 面向实现具体 写法public  void  eat(Meat meat){System.out.println(meat.eat());}
}

上面这个代码写的客户吃东西的案例,普通写法是没有接口的,后面要写依赖倒置原则所以也加上了,在上面可以看到,依赖倒置写法使用接口来制定好规范和契约,把展现的细节交给他们的实现类去完成,这就实现了,抽象不应该依赖细节,细节应该依赖抽象。也体现了要面向接口编程,不要面向实现编程的核心思想。

5、里氏替换原则

麻省理工学院一位叫做里斯科夫的女士提出来的,这是对继承更深的理解。
她提出:继承必须确保超类所拥有的性质在子类中仍然成立
翻译过来就是,子类继承父类,父类所拥有的性质仍然存在。也就是说子类可以扩展父类的功能,但是不能修改父类原有的功能。如果子类把父类的方法都重写了,那继承又有什么用呢?如果非得重写父类的方法,可以让父类和子类都继承一个更通俗的基类,原有的继承关系去掉,采用依赖、聚合、组合等关系代替才是符合里氏替换原则。
优点:加强程序的健壮性,同时变更时可以做到非常好的兼容性,提高程序的维护性、可扩展性。

package com.principle;public class Liskov {public static void main(String[] args) {son1 son1 = new son1();son1.sing();son1.sing1();}
}class father {void sing() {System.out.println("精通粤语、英语等各种年代的歌");}void  work(){System.out.println("精通Java、PHP、go等流行语言");}void Hair(){System.out.println("十年程序员标准发量,地中海可还行");}}
class son extends father{//除了father的技能外 还会跳舞void dance(){System.out.println("练习俩年半的篮球杂技舞蹈");}//修改了father的良好基因void sing(){System.out.println("不好意思,我只会rap了");}}
//这个时候我们要son唱歌,他肯定开口就是哟哟哟切克闹,因为他重写了father的方法,不符合里氏替换规则 因此做以下修过
//让父类和子类都继承一个更通俗的基类 去除原来的继承关系 采用依赖、聚合、组合等关系代替才是符合里氏替换原则
//基类
class base{}
//父类
class  father1 extends base{void sing() {System.out.println("精通粤语、英语等各种年代的歌");}}
//子类
class son1 extends  base{//组合关系 不再是父子 而是兄弟搭档 son1需要自己的rap也需要兄弟的sing技能private father1 father1= new father1();//son1的rapvoid sing(){System.out.println("不好意思,我只会rap了");}//father1的singvoid sing1(){this.father1.sing();}
}

在日常开发中,我们重写父类的方法很常见。但是里氏替换原则是一个标准,或者说是一种规范。我们应该向这个原则靠,里氏替换原则也是实现开闭原则的重要方式之一。

6、合成复用原则

合成复用原则:它要求在软件复用时,要尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。
因为继承的耦合性很高,不利于类的扩展和维护。如果要使用继承,就得遵守里氏替换原则。能用组合聚合关系尽量用组合聚合。因为这个原则比较简单,而且上个原则也写到过它的代码。所以这里就不在啰嗦,但是这个原则和开闭原则一样,是相当重要的。
合成复用原则同里氏替换原则相辅相成的,两者都是开闭原则的具体实现规范。

7、迪米特法则

官方定义:Talk only to your immediate friends and not to strangers
只与你的直接朋友交谈,不跟“陌生人”说话,也叫做最少知道原则。
如果两个软件实体无须直接通信,那么就不应当发生直接的相互调用,可以通过第三方转发该调用。其目的是降低类之间的耦合度,提高模块的相对独立性。
这里引用网上代码做为示例
明星与经纪人的关系实例。
分析:明星由于全身心投入艺术,所以许多日常事务由经纪人负责处理,如与粉丝的见面会,与媒体公司的业务洽淡等。这里的经纪人是明星的朋友,而粉丝和媒体公司是陌生人,所以适合使用迪米特法则

package principle;public class LoDtest {public static void main(String[] args) {Agent agent = new Agent();agent.setStar(new Star("林心如"));agent.setFans(new Fans("粉丝韩丞"));agent.setCompany(new Company("中国传媒有限公司"));agent.meeting();agent.business();}
}//经纪人
class Agent {private Star myStar;private Fans myFans;private Company myCompany;public void setStar(Star myStar) {this.myStar = myStar;}public void setFans(Fans myFans) {this.myFans = myFans;}public void setCompany(Company myCompany) {this.myCompany = myCompany;}public void meeting() {System.out.println(myFans.getName() + "与明星" + myStar.getName() + "见面了。");}public void business() {System.out.println(myCompany.getName() + "与明星" + myStar.getName() + "洽淡业务。");}
}//明星
class Star {private String name;Star(String name) {this.name = name;}public String getName() {return name;}
}//粉丝
class Fans {private String name;Fans(String name) {this.name = name;}public String getName() {return name;}
}//媒体公司
class Company {private String name;Company(String name) {this.name = name;}public String getName() {return name;}
}

总结

以上原则的核心思想主要是

  • 考虑到可能变化的部分,使其独立,变化的代码尽可能不影响其他代码。
  • 针对接口编程,而不是针对实现编程。重在抽象设计,而不是具体实现细节。
  • 从耦合性,内聚性,可维护性、可读性、可扩展性、重用性、灵活性等多方面去思考。

Java思想进阶之设计模式解析前篇(七大原则)相关推荐

  1. 【设计模式】软件设计七大原则

    做好自己 软件设计七大原则 开闭原则OCP(Open-Closed Principle) 依赖倒转原则DIP(Dependence Inversion Principle) 单一职责原则SRP(Sin ...

  2. 设计模式(面向对象)设计的七大原则

    声明:本人设计模式模块是集合网上资料和老师课件总结的知识点,如本博客有侵权,本人即刻删. 设计模式(面向对象设计)原则,分别是: 1.开放封闭原则:对扩展开放,对修改关闭 2.单一职责原则:一个类只做 ...

  3. 设计模式 - 软件设计的七大原则

    文章目录 前言 1. 软件设计模式原则 2. 开闭原则 1. 概念 2. 例子 3. 里氏替换原则 1. 概念 2. 例子 4. 依赖倒置原则 1. 概念 2. 代码 5. 单一职责原则 说明 6. ...

  4. 【设计模式】软件设计七大原则 ( 开闭原则 )

    文章目录 一.开闭原则简介 二.开闭原则代码示例 1.商品接口 2.普通商品类 3.折扣商品类 4.测试类 一.开闭原则简介 开闭原则 : 定义 : 一个 软件实体 , 类 / 模块 / 函数 , 对 ...

  5. 实例图解设计模式之面向对象设计七大原则

    文章目录 面向对象设计原则详解 面向对象设计原则概述 常用的面向对象设计原则 单一职责原则(Single Responsibility Principe)SRP ★★★★☆ 开闭原则(Open-Clo ...

  6. 【设计模式】软件设计七大原则 ( 接口隔离原则 | 代码示例 )

    文章目录 一.接口隔离原则简介 二.接口隔离原则代码示例 ( 反面示例 ) 1.接口定义 ( 接口臃肿 ) 2.实现类 1 3.实现类 2 三.接口隔离原则代码示例 ( 推荐用法 ) 1.接口 1 2 ...

  7. 【设计模式】软件设计七大原则 ( 迪米特原则 | 代码示例 )

    文章目录 一.迪米特原则简介 二.迪米特原则代码示例 ( 反面示例 ) 1.经理类 2.员工类 3.商品类 4.测试类 三.迪米特原则代码示例 ( 推荐用法 ) 1.经理类 2.员工类 3.商品类 4 ...

  8. 【设计模式】软件设计七大原则 ( 合成复用原则 | 代码示例 )

    文章目录 一.合成复用原则简介 二.合成复用 与 继承复用 优缺点 三.合成复用原则代码示例 1.继承复用代码示例 2.合成复用代码示例 一.合成复用原则简介 合成复用原则 又称为 组合复用原则 , ...

  9. 【设计模式】软件设计七大原则 ( 里氏替换原则 | 定义 | 定义扩展 | 引申 | 意义 | 优点 )

    文章目录 一.里氏替换原则定义 二.里氏替换原则定义扩展 三.里氏替换原则引申意义 四.里氏替换原则意义 五.里氏替换原则优点 一.里氏替换原则定义 里氏替换原则定义 : 如果 对每一个 类型为 T1 ...

最新文章

  1. vue 网络请求 axios vue POST请求 vue GET请求 代码示例
  2. SQL------Hint
  3. sybase游标使用方法
  4. C++学习之路 | PTA乙级—— 1049 数列的片段和 (20 分)(精简)
  5. 软件配置,软件配置及变更管理的重要意义与价值
  6. 数学之美 与 浪潮之巅
  7. 2017年终总结,开始写博客的第一年
  8. android编程微博的发送,基于Android手机微博客户端的开发.doc
  9. 量子笔记:量子计算祛魅
  10. QT 中文语法错误: 缺少“(” (在“}”的前面)(所遇到的特殊情况)
  11. 网络打印机计算机服务,在Windows7中添加网络打印机的解决方案提示“本地打印机后台处理程序服务未运行”...
  12. spark idea报错:json standard allows only one-top level
  13. 记一次简单的分区加LVM划分练习
  14. Unity | 基础逻辑
  15. sau交流学习社区第三方登陆github--oauth来实现用户登录
  16. 时间序列的分析和预测
  17. 1 php方式实现购物车原理,PHP购物车实现的原理
  18. 5、获取蓝牙设备列表(getBluetoothDevices)
  19. 每日安全简讯20160719
  20. 什么是超大规模数据中心?它们是如何工作的?

热门文章

  1. 【考研英语语法】祈使句
  2. 【ManageEngine】终端管理系统,助力华盛证券数字化转型
  3. 51nod1693 水群
  4. ES中 同时使用should和must 导致只有must生效 解决方案
  5. 论文笔记——EXPLAINING AND HARNESSING ADVERSARIAL EXAMPLES(解释和利用对抗样本)
  6. npoi获取合并单元格_NPOI合并单元格
  7. MySQL 所推荐的左右值法(毗邻目录法、预排序历遍法)
  8. 程序员实习过程中应该掌握的问问题技巧
  9. 攻城略地mysql充值_攻城掠地充值有巨惠!平台折扣5.0超划算
  10. Pyqt搭建YOLOV3目标检测界面(超详细+源代码)