【设计模式-七大原则】
一、开放-封闭原则(Open-Closed Principle:OCP)
定义
软件实体应当对扩展开放,对修改关闭
。这句话说得有点专业,更通俗一点讲,也就是:软件系统中包含的各种组件,例如模块(Modules)、类(Classes)以及功能(Functions)等等,应该在不修改现有代码的基础上,去扩展新功能。
问题由来
凡事的产生都有缘由。开闭原则的产生缘由。在软件的生命周期内,因为变化、升级和维护等原因需要对软件原有代码进行修改时,可能会给旧代码中引入错误,也可能会使我们不得不对整个功能进行重构,并且需要对原有代码进行重新测试。这就对我们的整个系统的影响特别大,这也充分展现出了系统的耦合性如果太高,会大大的增加后期的扩展,维护。为了解决这个问题,故人们总结出了开闭原则。解决开闭原则的根本其实还是在解耦合。所以,我们面向对象的开发,我们最根本的任务就是解耦合。
解决方法
当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。
小结
开闭原则具有理想主义的色彩,说的很抽象,它是面向对象设计的终极目标。其他几条原则,则可以看做是开闭原则的实现。我们要用抽象构建框架,用实现扩展细节。
二、单一职责原则(Single Responsibility Principle)
定义
一个类,只有一个引起它变化的原因
。即:应该只有一个职责。
每一个职责都是变化
的一个轴线,如果一个类有一个以上的职责,这些职责就耦合在了一起。这会导致脆弱的设计。当一个职责发生变化时,可能会影响其它的职责。另外,多个职责耦合在一起,会影响复用性。例如:要实现逻辑和界面的分离。需要说明的一点是单一职责原则不只是面向对象编程思想所特有的,只要是模块化的程序设计,都需要遵循这一重要原则。
问题由来
类T负责两个不同的职责:职责P1,职责P2。当由于职责P1需求发生改变而需要修改类T时,有可能会导致原本运行正常的职责P2功能发生故障。
解决方法
分别建立两个类T1、T2,使T1完成职责P1功能,T2完成职责P2功能。这样,当修改类T1时,不会使职责P2发生故障风险;同理,当修改T2时,也不会使职责P1发生故障风险。
三、里氏替换原则(Liskov Substitution Principle)
定义
子类型必须能够替换掉它们的父类型
。注意这里的能够
两字。有人也戏称老鼠的儿子会打洞原则。尽量不要重写父类的方法,也尽量不要重载父类的方法。
问题由来
有一功能P1,由类A完成。现需要将功能P1进行扩展,扩展后的功能为P,其中P由原有功能P1与新功能P2组成。新功能P由类A的子类B来完成,则子类B在完成新功能P2的同时,有可能会导致原有功能P1发生故障。(B在不修改父类A的方式时,P1功能会正常,当我们重写会重载了父类方法可能会导致功能P1发生故障。)
解决方法
类B继承类A时,除添加新的方法完成新增功能P2外,尽量不要重写父类A的方法,也尽量不要重载父类A的方法。
小结
所有引用父类的地方必须能透明地使用其子类的对象。类可以扩展父类的功能,但不能改变父类原有的功能。即:子类可以实现父类的抽象方法,子类也中可以增加自己特有的方法,但不能覆盖父类的非抽象方法。当子类的方法重载父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。
四、迪米特法则(Law Of Demeter)
4.1 基础
定义
迪米特法则又叫最少知道原则。即:一个对象应该对其他对象保持最少的了解。
如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。简单定义为只与直接的朋友通信。首先来解释一下什么是直接的朋友:每个对象都会与其他对象有耦合关系,只要两个对象之间有耦合关系,我们就说这两个对象之间是朋友关系。耦合的方式很多,依赖、关联、组合、聚合等
。其中,我们称出现成员变量、方法参数、方法返回值
中的类为直接的朋友
,而出现在局部变量中的类则不是直接的朋友。也就是说,陌生的类最好不要作为局部变量的形式出现在类的内部。
问题由来
类与类之间的关系越密切,耦合度越大,当一个类发生改变时,对另一个类的影响也越大。
最早是在1987年由美国Northeastern University的Ian Holland提出。通俗的来讲,就是一个类对自己依赖的类知道的越少越好。也就是说,对于被依赖的类来说,无论逻辑多么复杂,都尽量地的将逻辑封装在类的内部,对外除了提供的public方法,不对外泄漏任何信息。迪米特法则还有一个更简单的定义:只与直接的朋友通信。
解决方法
尽量降低类与类之间的耦合。 自从我们接触编程开始,就知道了软件编程的总的原则:低耦合,高内聚。无论是面向过程编程还是面向对象编程,只有使各个模块之间的耦合尽量的低,才能提高代码的复用率。
迪米特法则的初衷是降低类之间的耦合
,由于每个类都减少了不必要的依赖,因此的确可以降低耦合关系。但是凡事都有度,虽然可以避免与非直接的类通信,但是要通信,必然会通过一个“中介”来发生联系。故过分的使用迪米特原则,会产生大量这样的中介和传递类,导致系统复杂度变大。所以在采用迪米特法则时要反复权衡,既做到结构清晰,又要高内聚低耦合。
4.2 代码示例
4.2.1 说明
说明
有一个集团公司,下属单位有分公司和直属部门,现在要求打印出所有下属单位的员工ID。先来看一下违反迪米特法则的设计。
4.2.2 不符合迪米特法则
代码
// 总公司员工
class Employee {private String id;public void setId(String id) {this.id = id;}public String getId() {return id;}
}// 分公司员工
class SubEmployee {private String id;public void setId(String id) {this.id = id;}public String getId() {return id;}
}// 子公司管理
class SubCompanyManager {// 获取子公司所有的人员public List<SubEmployee> getAllEmployee() {List<SubEmployee> list = new ArrayList<SubEmployee>();for (int i = 0; i < 100; i++) {SubEmployee emp = new SubEmployee();// 为分公司人员按顺序分配一个IDemp.setId("分公司" + i);list.add(emp);}return list;}
}// 总公司管理
class CompanyManager {// 获取总公司人员public List<Employee> getAllEmployee() {List<Employee> list = new ArrayList<Employee>();for (int i = 0; i < 30; i++) {Employee emp = new Employee();// 为总公司人员按顺序分配一个IDemp.setId("总公司" + i);list.add(emp);}return list;}// 打印所有人员(包括总公司和分公司)public void printAllEmployee(SubCompanyManager sub) {// 子公司【SubEmployee对象不是CompanyManager的直接朋友,SubEmployee作为局部变量不是CompanyManager的直接朋友。】List<SubEmployee> list1 = sub.getAllEmployee();for (SubEmployee e : list1) {System.out.println(e.getId());}// 总公司List<Employee> list2 = this.getAllEmployee();for (Employee e : list2) {System.out.println(e.getId());}}
}public class Client {public static void main(String[] args) {CompanyManager e = new CompanyManager();e.printAllEmployee(new SubCompanyManager());}
}
不符合说明
主要问题出在CompanyManager中,根据迪米特法则,只与直接的朋友发生通信,而SubEmployee类并不是CompanyManager类的直接朋友
(以局部变量出现的耦合不属于直接朋友),从逻辑上讲总公司只与他的分公司耦合就行了,与分公司的员工并没有任何联系,这样设计显然是增加了不必要的耦合。按照迪米特法则,应该避免类中出现这样非直接朋友关系的耦合。
4.2.3 符合迪米特法则
代码
// 子公司【SubEmployee作为SubCompanyManager的返回值,是直接朋友,可在该类中直接打印分公司的人员id。】
class SubCompanyManager {public List<SubEmployee> getAllEmployee() {List<SubEmployee> list = new ArrayList<SubEmployee>();for (int i = 0; i < 100; i++) {SubEmployee emp = new SubEmployee();// 为分公司人员按顺序分配一个IDemp.setId("分公司" + i);list.add(emp);}return list;}public void printEmployee() {List<SubEmployee> list = this.getAllEmployee();for (SubEmployee e : list) {System.out.println(e.getId());}}
}// 总公司【SubCompanyManager作为CompanyManager的参数,是直接朋友,可调用SubCompanyManager中的打印分公司人员的id方法。】
// 【CompanyManager没有再引用SubEmployee类,只与直接朋友交互,符合迪米特法则。】
class CompanyManager {public List<Employee> getAllEmployee() {List<Employee> list = new ArrayList<Employee>();for (int i = 0; i < 30; i++) {Employee emp = new Employee();// 为总公司人员按顺序分配一个IDemp.setId("总公司" + i);list.add(emp);}return list;}public void printAllEmployee(SubCompanyManager sub) {sub.printEmployee();List<Employee> list2 = this.getAllEmployee();for (Employee e : list2) {System.out.println(e.getId());}}
}
五、依赖倒置原则(Dependence Inversion Principle)
5.1 基础
定义
高层模块不应该依赖低层模块
,二者都应该依赖其抽象
;抽象不应该依赖细节;细节应该依赖抽象
中心思想是面向接口编程。
问题由来
将类A修改为依赖接口I,类B和类C各自实现接口I,类A通过接口I间接与类B或者类C发生联系,则会大大降低修改类A的几率。
在实际编程中,我们一般需要做到如下3点:
低层模块尽量都要有抽象类或接口,或者两者都有。
变量的声明类型尽量是抽象类或接口
使用继承时遵循里氏替换原则
采用依赖倒置原则尤其给多人合作开发带来了极大的便利,参与协作开发的人越多、项目越庞大,采用依赖导致原则的意义就越重大。
小结
依赖倒置原则就是要我们面向接口编程
,理解了面向接口编程,也就理解了依赖倒置。
5.2 代码示例
5.2.1 不符合依赖倒置原则
前提说明
一个爱学习的吴同学现在正在学习设计模式和Java课程。伪代码如下:
public class Study {public void studyJavaCourse() {System.out.println("吴同学正在学习Java课程");}public void studyDesignPatternCourse() {System.out.println("吴同学正在学习设计模式课程");}
}
模拟高层模块调用
public static void main(String[] args) {Study study = new Study();study.studyJavaCourse();study.studyDesignPatternCourse();
}
不规范说明
原因1:有效控制影响范围
由于吴同学热爱学习,随着学习兴趣的 “暴增”,可能会继续学习AI(人工智能)的课程。这个时候,因为业务的扩展,要从底层实现到高层调用依次地修改代码。
我们需要在Study类中新增studyAICourse()方法,也需要在高层模块中增加调用,这样一来,系统发布后,其实是非常不稳定的。显然在这个简单的例子中,我们还可以自信地认为,我们能Hold住这一次的修改带来的影响,因为都是新增的代码,我们回归的时候也可以很好地 cover住,但实际的情况和实际的软件环境要复杂得多。
最理想的情况就是,我们已经编写好的代码可以 “万年不变”,这就意味着已经覆盖的单元测试可以不用修改,已经存在的行为可以保证保持不变,这就意味着稳定。任何代码上的修改带来的影响都是有未知风险的,不论看上去多么简单。
原因2:增强代码可读性和可维护性
另外一点,你有没有发现其实加上新增的AI课程的学习,他们三节课本质上行为都是一样的,如果我们任由这样行为近乎一样的代码在我们的类里面肆意扩展的话,很快我们的类就会变得臃肿不堪,等到我们意识到不得不重构这个类以缓解这样的情况的时候,或许成本已经变得高得可怕了。
原因3:降低耦合
举例:在商品经济的萌芽时期,出现了物物交换。假设你要买一个iPhone,卖iPhone的老板让你拿一头猪跟他换,可是你并没有养猪,你只会编程。所以你找到一位养猪户,说给他做一个养猪的APP来换他一头猪,他说换猪可以,但是得用一条金项链来换。
所以这里就出现了一连串的对象依赖,从而造成了严重的耦合灾难。解决这个问题的最好的办法就是,买卖双发都依赖于抽象(也就是货币)来进行交换,这样一来耦合度就大为降低了。
5.2.2 符合依赖倒置原则
定义一个课程的抽象ICourse接口
public interface ICourse {void study();
}
然后编写分别为JavaCourse和DesignPatternCourse编写一个类
public class JavaCourse implements ICourse {@Overridepublic void study() {System.out.println("吴同学正在学习Java课程");}
}public class DesignPatternCourse implements ICourse {@Overridepublic void study() {System.out.println("吴同学正在学习设计模式课程");}
}
然后把Study类改造成成如下
public class Study {public void studyCourse(ICourse course) {course.study();}
}
调用
public static void main(String[] args) {Study study = new Study();study.studyCourse(new JavaCourse());study.studyCourse(new DesignPatternCourse());
}
5.2.3 总结
小结
这时候我们再来看代码,无论吴同学的兴趣怎么暴涨,对于新的课程,都只需要新建一个类,通过参数传递的方式告诉它,而不需要修改底层的代码。实际上这有点像大家熟悉的依赖注入的方式了。
总之,切记:以抽象为基准比以细节为基准搭建起来的架构要稳定得多,因此在拿到需求后,要面相接口编程,先顶层设计再细节地设计代码结构
。
六、接口隔离原则(Interface Segregation Principle)
6.1 基础
定义
客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口
上。
问题由来
类A通过接口I依赖类B,类C通过接口I依赖类D,如果接口I对于类A和类B来说不是最小接口,则类B和类D必须去实现他们不需要的方法。
即将臃肿的接口I拆分为独立的几个接口,类A和类C分别与他们需要的接口建立依赖关系。也就是采用接口隔离原则。
使用特点
根据接口隔离原则,当一个接口太大时,我们需要将它分割成一些更细小的接口。使用该接口的客户端仅需知道与之相关的方法即可。每一个接口应该承担一种相对独立的角色,不干不该干的事,该干的事都要干。这里的“接口”往往有两种不同的含义:一种是指一个类型所具有的方法特征的集合,仅仅是一种逻辑上的抽象;另外一种是指某种语言具体的“接口”定义,有严格的定义和结构,比如Java语言中的interface。对于这两种不同的含义,ISP的表达方式以及含义都有所不同:
当把“接口”理解成一个类型所提供的所有方法特征的集合的时候,这就是一种逻辑上的概念,接口的划分将直接带来类型的划分。可以把接口理解成角色,一个接口只能代表一个角色,每个角色都有它特定的一个接口,此时,这个原则可以叫做“角色隔离原则”。
如果把“接口”理解成狭义的特定语言的接口,那么ISP表达的意思是指接口仅仅提供客户端需要的行为,客户端不需要的行为则隐藏起来,应当为客户端提供尽可能小的单独的接口,而不要提供大的总接口。在面向对象编程语言中,实现一个接口就需要实现该接口中定义的所有方法,因此大的总接口使用起来不一定很方便,为了使接口的职责单一,需要将大接口中的方法根据其职责不同分别放在不同的小接口中,以确保每个接口使用起来都较为方便,并都承担某一单一角色。接口应该尽量细化,同时接口中的方法应该尽量少,每个接口中只包含一个客户端(如子模块或业务逻辑类)所需的方法即可,这种机制也称为“定制服务”,即为不同的客户端提供宽窄不同的接口。
6.2 案例举例
6.2.1 不符合接口隔离原则
图示
说明
这个图的意思是:类A依赖接口I中的方法1、方法2、方法3;类B是对类A依赖的实现。类C依赖接口I中的方法1、方法4、方法5,类D是对类C依赖的实现。对于类B和类D来说,虽然他们都存在着用不到的方法(也就是图中红色字体标记的方法),但由于实现了接口I,所以也必须要实现这些用不到的方法。对类图不熟悉的可以参照程序代码来理解。
代码
interface I {public void method1();public void method2();public void method3();public void method4();public void method5();
}class A {public void depend1(I i) {i.method1();}public void depend2(I i) {i.method2();}public void depend3(I i) {i.method3();}
}class B implements I {public void method1() {System.out.println("类B实现接口I的方法1");}public void method2() {System.out.println("类B实现接口I的方法2");}public void method3() {System.out.println("类B实现接口I的方法3");}// 对于类B来说,method4和method5不是必需的,但是由于接口A中有这两个方法。// 所以在实现过程中即使这两个方法的方法体为空,也要将这两个没有作用的方法进行实现。public void method4() {}public void method5() {}
}class C {public void depend1(I i) {i.method1();}public void depend2(I i) {i.method4();}public void depend3(I i) {i.method5();}
}class D implements I {public void method1() {System.out.println("类D实现接口I的方法1");}// 对于类D来说,method2和method3不是必需的,但是由于接口A中有这两个方法。// 所以在实现过程中即使这两个方法的方法体为空,也要将这两个没有作用的方法进行实现。public void method2() {}public void method3() {}public void method4() {System.out.println("类D实现接口I的方法4");}public void method5() {System.out.println("类D实现接口I的方法5");}
}public class Client {public static void main(String[] args) {A a = new A();a.depend1(new B());a.depend2(new B());a.depend3(new B());C c = new C();c.depend1(new D());c.depend2(new D());c.depend3(new D());}
}
解释
可以看到,如果接口过于臃肿,只要接口中出现的方法,不管对依赖于它的类有没有用处,实现类中都必须去实现这些方法。这显然不是好的设计。如果将这个设计修改为符合接口隔离原则,就必须对接口I进行拆分。
6.2.2 符合接口隔离原则
图示
代码
interface I1 {public void method1();
}interface I2 {public void method2();public void method3();
}interface I3 {public void method4();public void method5();
}class A {public void depend1(I1 i) {i.method1();}public void depend2(I2 i) {i.method2();}public void depend3(I2 i) {i.method3();}
}class B implements I1, I2 {public void method1() {System.out.println("类B实现接口I1的方法1");}public void method2() {System.out.println("类B实现接口I2的方法2");}public void method3() {System.out.println("类B实现接口I2的方法3");}
}class C {public void depend1(I1 i) {i.method1();}public void depend2(I3 i) {i.method4();}public void depend3(I3 i) {i.method5();}
}class D implements I1, I3 {public void method1() {System.out.println("类D实现接口I1的方法1");}public void method4() {System.out.println("类D实现接口I3的方法4");}public void method5() {System.out.println("类D实现接口I3的方法5");}
}
6.3 总结
总结
接口隔离原则的含义是:建立单一接口,不要建立庞大臃肿的接口,尽量细化接口,接口中的方法尽量少。也就是说,我们要为各个类建立专用的接口,而不要试图去建立一个很庞大的接口供所有依赖它的类去调用。本文例子中,将一个庞大的接口变更为3个专用的接口所采用的就是接口隔离原则。在程序设计中,依赖几个专用的接口要比依赖一个综合的接口更灵活。接口是设计时对外部设定的“契约”,通过分散定义多个接口,可以预防外来变更的扩散,提高系统的灵活性和可维护性。
说到这里,很多人会觉的接口隔离原则跟之前的单一职责原则很相似,其实不然。其一,单一职责原则原注重的是职责;而接口隔离原则注重对接口依赖的隔离。其二,单一职责原则主要是约束类,其次才是接口和方法,它针对的是程序中的实现和细节;而接口隔离原则主要约束接口接口,主要针对抽象,针对程序整体框架的构建。
注意点
采用接口隔离原则对接口进行约束时,要注意以下几点:
接口尽量小,但是要有限度。对接口进行细化可以提高程序设计灵活性是不挣的事实,但是如果过小,则会造成接口数量过多,使设计复杂化。所以一定要适度。
为依赖接口的类定制服务,只暴露给调用的类它需要的方法,它不需要的方法则隐藏起来。只有专注地为一个模块提供定制服务,才能建立最小的依赖关系。
提高内聚,减少对外交互。使接口用最少的方法去完成最多的事情。
运用接口隔离原则,一定要适度。
接口设计的过大或过小都不好。设计接口的时候,只有多花些时间去思考和筹划,才能准确地实践这一原则。
七、合成/聚合原则(Composite/Aggregate Reuse Principle:CARP)
7.1 基础
定义
也有人叫做合成复用原则,及尽量使用合成/聚合,尽量不要使用类继承。换句话说,就是能用合成/聚合的地方,绝不用继承
。
就是在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分。
原则分析
在面向对象设计中,可以通过两种基本方法在不同的环境中复用已有的设计和实现,即通过
组合/聚合关系或通过继承
。继承复用
:实现简单,易于扩展。破坏系统的封装性;从基类继承而来的实现是静态的,不可能在运行时发生改变,没有足够的灵活性;只能在有限的环境中使用。( “白箱”复用)组合/聚合复用
:耦合度相对较低,选择性地调用成员对象的操作;可以在运行时动态进行。( “黑箱”复用)组合/聚合可以使系统更加灵活,
类与类之间的耦合度降低
,一个类的变化对其他类造成的影响相对较少,因此一般 首选使用组合/聚合来实现复用;其次才考虑继承,在使用继承时,需要严格遵循里氏代换原则,有效使用继承会有助于对问题的理解,降低复杂度,而滥用继承反而会增加系统构建和维护的难度以及系统的复杂度,因此需要慎重使用继承复用。此原则和里氏代换原则氏相辅相成的,两者都是具体实现"开-闭"原则的规范。违反这一原则,就无法实现"开-闭"原则,首先我们要明白合成和聚合的概念。
7.2 合成(组合)
概念
合成(组合):表示一个整体与部分的关系
, 指一个依托整体而存在的关系。( 整体与部分不可以分开
)
例如:一个人对他的房子和家具,其中他的房子和家具是不能被共享的,因为那些东西都是他自己的。并且人没了,这个也关系就没了。
虽然组合表示的是一个整体与部分的关系,但是组合关系中部分和整体具有统一的生存期。一旦整体对象不存在,部分对象也将不存在,部分对象与整体对象之间具有同生共死的关系。
图示
代码
public class Head {private Mouth mouth;public Head() {mouth = new Mouth();}
}public class Mouth {
}
7.3 聚合
概念
聚合是比合成关系更弱的一种拥有关系,也表示整体与部分的关系(整体与部分可以分开
)。
例如:一个奔驰S360汽车,对奔驰S360引擎,奔驰S360轮胎的关系。这些关系就是带有聚合性质的。因为奔驰S360引擎和奔驰S360轮胎他们只能被奔驰S360汽车所用,离开了奔驰S360汽车,它们就失去了存在的意义。在我们的设计中,这样的关系不应该频繁出现。这样会增大设计的耦合度。
意义
通常在定义一个整体类后,再去分析这个整体类的组成结构,从而找出一些成员类,该整体类和成员类之间就形成了聚合关系。在聚合关系中, 成员类是整体类的一部分,即成员对象是整体对象的一部分,但是成员对象可以脱离整体对象独立存在。 在UML中,聚合关系用带空心菱形的直线表示。
图示
代码
public class Car {private Engine engine;public Car(Engine engine) {this.engine = engine;}public void setEngine(Engine engine) {this.engine = engine;}
}public class Engine {
}
7.4 总结
梳理
明白了合成和聚合关系,再来理解合成/聚合原则应该就清楚了。要避免在系统设计中出现,一个类的继承层次超过3次。如果这样的话,可以考虑重构你的代码,或者重新设计结构.。当然最好的办法就是考虑使用合成/聚合原则。
原因
为什么要尽量使用合成/聚合而不使用类继承?
对象的继承关系在编译时就定义好了,所以无法在运行时改变从父类继承的子类的实现。
子类的实现和它的父类有非常紧密的依赖关系,以至于父类实现中的任何变化必然会导致子类发生变化。
当你复用子类的时候,如果继承下来的实现不适合解决新的问题,则父类必须重写或者被其它更适合的类所替换。这种依赖关系限制了灵活性,并最终限制了复用性。
八、总结
面向对象的原则
高内聚、低耦合。多聚合、少继承。
内聚:每个模块尽可能独立完成自己的功能,不依赖于模块外部的代码。
耦合:模块与模块之间接口的复杂程度,模块之间联系越复杂耦合度越高,牵一发而动全身。
目的:使得模块的“可重用性”、“移植性”大大增强。
聚合:事物A由若干个事物B组成,体现在类与类之间的关系就是:“类B的实例”作为“类A”的“成员对象”出现。
继承:顾名思义,体现在类与类之间的关系就是:“类B”被类A所继承。
【设计模式-七大原则】相关推荐
- Java面试之设计模式七大原则
最近项目不太忙,不怎么加班,正利用晚上时间好好学习学习设计模式,之前可能多多少少都用到过,但是有些还是很模糊,这下正好系统的学一下. 好了,话不多说,进入正题. 1.什么是设计模式? 软件工程中,设计 ...
- 第 2 章 设计模式七大原则
第 2 章 设计模式七大原则 1.设计模式的目的 编写软件过程中,程序员面临着来自 耦合性,内聚性以及可维护性,可扩展性,重用性,灵活性 等多方面的挑战, 设计模式是为了让程序(软件),具有如下更好的 ...
- 设计模式——七大原则(附代码示例)
一. 设计模式概念 对接口编程而不是对实现编程:优先使用对象组合而不是继承 二. 设计模式总览 1. 创建型模式(Creational Patterns):(5) 单例(Singlet ...
- 设计模式——七大原则
设计模式--七大原则 汇总篇 1.单一职责 2.接口隔离 3.依赖倒转 4.里氏代换原则 5.开闭原则 6.迪米特法则 7.合成复用 汇总篇 1.单一职责 对类来说的,即一个类应该只负责一项职责.如类 ...
- 图解设计模式-设计模式七大原则
Java设计模式 设计模式七大原则 设计模式的目的 编写软件过程中,程序员面临来自 耦合性,内聚性以及可维护性,可扩展性,重用性,灵活性等多方面的挑战,设计模式是为了让 **程序(软件)**具有更好的 ...
- Day305.设计模式七大原则 -Java设计模式
七大设计原则 一.设计模式的目的 编写软件过程中,程序员面临着来自 耦合性,内聚性以及可维护性,可扩展性,重用性,灵活性 等多方面的挑战,设计模式是为了让程序(软件),具有更好的↓↓↓ 1. 代码重用 ...
- Java设计模式七大原则-单一职责原则
目录 概述:设计模式的目的 设计模式七大原则 单一职责原则 单一职责原则注意事项和细节 概述:设计模式的目的 编写软件过程中,程序员面临着来自 耦合性,内聚性以及可维护性,可扩展性,重用性,灵活性 等 ...
- 设计模式七大原则介绍
文章目录 1. 设计模式有哪些种类 2. 设计模式的目的 3. 设计模式七大原则 3.1. 单一职责原则 1. 基本介绍 2. 模拟场景 2. 接口隔离原则 1. 基本介绍 2. 模拟场景 3. 依赖 ...
- 设计模式七大原则知识概括
设计模式七大原则知识概括 设计模式的目的 设计模式七大原则 单一职责原则 接口隔离原则 依赖倒转(倒置)原则 里氏替换原则 开闭原则 迪米特法则 合成复用原则 设计原则核心思想 设计模式的目的 目的: ...
- JAVA设计模式七大原则
设计模式七大原则 设计模式目的 1.代码重用性 2.可读性 3.可读性 4.扩展性 5.可靠性 6.高内聚低耦合 七大原则 1.单一职责原则 一个类或方法中只做一件事情 2.接口隔离原则 一个类通过接 ...
最新文章
- s:textfield format date
- 云原生系列「五」我为啥又看上了serviceMesh?
- Codeforces Round #653 (Div. 3)(A, B, C, D, E1详解)
- 8086地址传送指令LEA,LDS,LES
- node.js android 聊天,Node.js实现简单聊天服务器
- 微软“黑历史”:一个活了 45 年的愚蠢 Bug!
- 2020.7.20-每日进步
- 数据挖掘的数据集资源
- 虚拟机服务器系统蓝屏怎么办,虚拟机windows 2008 R2 系统蓝屏
- 模拟信号隔离转换模块0-10V0-5V转4-20mA0-20mA直流转换
- 服务器mtu值修改,更改服务器mtu值
- android系统时间获取方式
- 如何进行有效的大数据处理、分析?
- 经典sql基本语句大全
- 数值分析——LU分解求解线性方程组的Python实现
- python抓取京东的商品信息
- 如何营造性能至上的团队文化
- Unity3d 周分享(19期 2019.6.22 )
- win10, net framework 3.5 安装报错0x800F081F
- mysql基本语法DDL语句的总结 (笔记)