简介:类的功能要单一,不能包罗万象,跟杂货铺似的。
说明:对类来说的,即一个类应该只负责一项职责(不是说一个类里只能有一个方法,指的是一项职责,比如这个类管订单了,就不要去管物流。)
,如类A负责两个不同职责: 职责1,职责2。当职责1需求变更而改变A时,可能造成职责2执行错误,所以需要将类A的粒度分解为 A1,A2
单一职责原则注意事项和细节
例子:
// 方式1
// 1.在方式1的run方法中,违反了单一职责原则
// 2. 解决的方案非常的简单,根据交通工具运行方法不同,分解成不同类即可
class Vehicle {
public void run(String vehicle)
System.out.println(vehicle+"在公路上运行..");
}
}
// 方案2的分析
// 1.遵守单一职责原则
// 2.但是这样做的改动很大,即将类分解,同时修改客户端
// 改进:直接修改Vehicle类,改动的代码会比较少 =>方案3
class WaterVelhjicle {
public void run(String vehicle) {
System.out.println(vehicle + "水中运行");
}
}
class AirVehicle {
public void run(String vehicle) {
System.out.println(vehicle + "天空运行");
}
}
// 方式3
// 1.这种修改方法没有对原来的类做大的修改,只是增加方法
// 2. 这里虽然没有在类这个级别上遵守单一 职责原则,但是在方法级别上,仍然是遵守单一职责
class Vehicle2 {
public void run(String vehicle) {
//处理
System.out.println(vehicle+"在公路上运行..");
}
public void runAir(String vehicle) {
System.out.println(vehicle+"在天空上运行...");
}
}
简介:一个模块对于拓展是开放的,对于修改是封闭的,想要增加功能热烈欢迎,想要修改,哼,一万个不乐意。
基本概念:
对扩展开放,对修改关闭。用抽象构建框架,用实现扩展细节
。当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化
。使用设计模式的目的就是遵循开闭原则
。public class Test {
public static void main(String[] args) {}
}
class GraphicEditor {
public void drawShape(Shape s){
if (s.m_ _type== 1)
drawRectangle(s);
elseif(s.m_ type== 2)
drawCircle(s);
}
public void drawRectangle(Shape r) {
System.out.println("矩形");}
public void drawCircle(Shaper) {
System.out.println("圆形");
}
}
class Shape {
int m_ _type;
}
class Rectangle extends Shape {
Rectangle(){
super.m_ type = 1;
}}
class Circle extends Shape {
Circle(){
super.m_ type= 2;
}
}
对扩展开放(提供方),对修改关闭(使用方)。即当我们给类增加新功能的时候,尽量不修改代码,或者尽可能少修改代码.
改进思路分析:
思路: 把创建Shape类做成抽象类,并提供一个抽象的draw方法,让子类去实现即可,这样我们有新的图形种类时,只需要让新的图形类继承Shape,并实现draw方法即可,使用方的代码就不需要修。满足了开闭原则
简介:子类可以替换父类出现在父类能够出现的任何地方。比如你能代表你爸去你姥姥家干活。哈哈~~
背景——OO中的继承性的思考和说明:
父类中凡是已经实现好的方法,实际上是在设定规范和契约
,虽然它不强制要求所有的子类必须遵循这些契约,但是如果子类对这些已经实现的方法任意修改,就会对整个继承体系造成破坏。使用继承会给程序带来侵入性,降低程序的可移植性降低,增加对象间的耦合性
,如果一个类被其他的类所继承,则当这个类需要修改时,必须考虑到所有的子类,并且父类修改后,所有涉及到子类的功能都有可能产生故障里氏替换原则:
所有引用基类的地方必须能透明地使用其子类的对象
。在子类中尽量不要重写父类的方法
继承实际上让两个类耦合性增强了,在适当的情况下,可以通过聚合,组合,依赖来解决问题
。在实际编程中,我们常常会通过重写父类的方法完成新的功能,这样写起来虽然简单,但整个继承体系的复用性会比较差。特别是运行多态比较频繁的时候
原有的继承关系去掉,采用依赖,聚合,组合等关系代替.
简介:高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象。抽象不应该依赖于具体实现,具体实现应该依赖于抽象。就是你出国要说你是中国人,而不能说你是哪个村子的。比如说中国人是抽象的,下面有具体的xx省,xx市,xx县。你要依赖的抽象是中国人,而不是你是xx村的。
说明: 依赖倒转原则(Dependence Inversion Principle)是指:
修正代码:
依赖关系传递的三种方式和应用案例:
依赖倒转原则的注意细节:
简介:客户端不应该依赖它不需要的接口
,即一个类对另一个类的依赖应该建立在最小的接口上。
说明:设计时采用多个与特定客户类有关的接口比采用一个通用的接口要好。就比如一个手机拥有打电话,看视频,玩游戏等功能,把这几个功能拆分成不同的接口,比在一个接口里要好的多。
例子:
下图是我们编码中遇到的常见问题:
类A通过接口Interface1依赖类B,类c通过接口Interface1依赖类D,如果接口Interface1对于类A和类c来说不是最小接口,那么类B和类D必须去实现他们不需要的方法。
//接口
interface Interface1 {
void operation1();
void operation2();
void operation3();
void operation4();
void operation5();
}
class B implements Interface1 {
void operation1() {
System. out. println();
}
void operation2(){
System. out. println();
}
void operation3(){
System. out. println();
}
void operation4(){
System. out. println();
}
void operation5() {
System. out. println();
}
}
class D implements Interface1 {
void operation1() {
System. out. println();
}
void operation2(){
System. out. println();
}
void operation3(){
System. out. println();
}
void operation4(){
System. out. println();
}
void operation5() {
System. out. println();
}
}
class A { //A 类通过接口Interface1依赖(使用) B类,但是只会用到1,2,3方法
public void depend1(Interface1 i) {
i. operation1();
}
public void depend2(Interface1 i) {
i. operation2();
}
public void depend3(Interface1 i) {
i. operation3();
}
}
class D { //D 类通过接口Interface1依赖(使用) D类,但是只会用到1,4,5方法
public void depend1(Interface1 i) {
i. operation1();
}
public void depend2(Interface1 i) {
i. operation4();
}
public void depend3(Interface1 i) {
i. operation5();
}
}
按隔离原则应当这样处理:
将接口Interface1 拆分为独立的几个接口,类A和类c分别与他们需要的接口建立依赖关系。也就是采用接口隔离原则
interface Interface1 {
void operation1();
}
//接口2
interface Interface2 {
void operation2();
void operation3();
}
//接口3
interface Interface3 {
void operation4();
void operation5();
}
class A {
public void depend1(Interface1 i) {
i.operation1();
}
public void depend2(Interface2 i) {
i. operation2();
}
public void depend3(Interface2 i) {
i. operation3();
}
}
class C {
public void depend1(Interface1 i) {
i . operation1();
}
public void depend4(Interface3 i) {
i. operation4();
}
public void depend5(Interface3| i) {
i. operation5();
}
}
简介:一个软件实体应当尽可能少的与其他实体发生相互作用
基本概念:
直接的朋友:
每个对象都会与其他对象有耦合关系,只要两个对象之间有耦合关系,我们就说这两个对象之间是朋友关系。
耦合的方式很多,依赖,关联,组合,聚合等。其中,我们称出现成员变量,方法参数,方法返回值中的类为直接的朋友
,而出现在局部变量中的类不是直接的朋友。也就是说,陌生的类最好不要以局部变量的形式出现在类的内部
。
迪米特法则注意事项和细节:
迪米特法则只是要求降低类间(对象间)耦合关系,并不是要求完全没有依赖关系
简介:尽量使用合成/聚合达到复用,尽量少用继承。原则: 一个类中有另一个类的对象
例子:
B类需要使用A类的方法,可以使用继承。但是使用继承会让B与A的耦合性增强。
改进,将A作为参数传入B类的方法中(即,依赖关系),B类依然可以使用到A类的方法。
或者使用组合关系
设计原则的核心思想
依赖——a依赖b,说明a使用b (dependency)
姐(接口隔离原则)和(合成复用原则)弟(迪米特法则)依(依赖倒置原则)理(里氏替换原则)开(开闭原则)战(单一职责原则)。
身为程序员,我们不需要华丽的编程技巧,高深的代码,对于我们来说只需要熟练的掌握业界给予我们总结的23种设计模式,才是最重要的。因为掌握这23种设计模式,你就可以成为不一般的开发人员了。
模式: 在一定环境中解决某一问题的方案,包括三个基本元素–问题,解决方案和环境。大白话:在一定环境下,用固定套路解决问题。
设计模式(Design pattern): 是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码变成真正工程化。
设计模式的分类:
创建型模式: 通常和对象的创建有关,涉及到对象实例化的方式。(共 5 种模式)
结构型模式: 描述的是如何组合类和对象以获得更大的结构。(共 7 种模式)
行为型模式: 用来对类或对象怎样交互和怎样分配职责进行描述。(共 11 种模式)
该模式用来处理对象的创建过程,主要包含以下五种设计模式:(单原建抽象工厂)
1, 工厂方法模式(Factory Method Pattern)的用意是定义一个创建产品对象的工厂接口, 将实际创建工作推迟到子类中。
2,抽象工厂模式(Abstract Factory Pattern)的意图是提供一个创建一系列相关或者相互依赖的接口,而无需指定它们具体的类。
3,建造者模式(Builder Pattern)的意图是将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
4,原型模式(Prototype Pattern)是用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
5,单例模式(Singleton Pattern)是保证一个类仅有一个实例,并提供一个访问它的全局访问点。
创建型模式有五种:工厂方法模式 、抽象工厂模式 、单例模式 、建造者模式 、原型模式
口诀:原来的建设工人单独抽奖
解释:原(原型模式)来的建(建造者模式)设工(工厂方法模式)人单(单例模式)独抽(抽象方法模式)奖。
6,代理模式(Proxy Pattern)就是为其他对象提供一种代理以控制对这个对象的访问。
7,装饰者模式(Decorator Pattern)动态的给一个对象添加一些额外的职责。就增加功能来说,此模式比生成子类更为灵活。
8,适配器模式(Adapter Pattern)是将一个类的接口转换成客户希望的另外一个接口。使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
9,桥接模式(Bridge Pattern)是将抽象部分与实际部分分离,使它们都可以独立的变化。
10,组合模式(Composite Pattern)是将对象组合成树形结构以表示“部分–整体”的层次结 构。使得用户对单个对象和组合对象的使用具有一致性。
11,外观模式(Facade Pattern)是为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
12,享元模式(Flyweight Pattern)是以共享的方式高效的支持大量的细粒度的对象。
结构型模式有七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式
口诀:经过小元代表的装饰、适配和组合,大桥的外观很nice。
解释:经过小元(享元模式)代表(代理模式)的装饰(装饰器模式)、适配(适配器模式)和组合(组合模式),大桥(桥接模式)的外观(外观模式)很nice。
13,模板方法模式(Template Method Pattern)使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
14,命令模式(Command Pattern)是将一个请求封装为一个对象,从而使你可用不同的请求对客户端进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
15,责任链模式(Chain of Responsibility Pattern),在该模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求,这使得系统可以在不影响客户端的情况下动态地重新组织链和分配责任。
16,策略模式(Strategy Pattern)就是准备一组算法,并将每一个算法封装起来,使得它们可以互换。
17,中介者模式(Mediator Pattern)就是定义一个中介对象来封装系列对象之间的交互。中介者使各个对象不需要显示的相互调用,从而使其耦合性松散,而且可以独立的改变他们 之间的交互。
18,观察者模式(Observer Pattern)定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
19,备忘录模式(Memento Pattern)是在不破坏封装的前提下,捕获一个对象的内部状态, 并在该对象之外保存这个状态。
20,访问者模式(Visitor Pattern)就是表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
21,状态模式(State Pattern)就是对象的行为,依赖于它所处的状态。
22,解释器模式(Interpreter Pattern)就是描述了如何为简单的语言定义一个语法,如何在该语言中表示一个句子,以及如何解释这些句子。
23,迭代器模式(Iterator Pattern)是提供了一种方法顺序来访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。
行为型模式有十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式
口诀:当车模他爹责备中介时,访问者命令观察者解释一下状态
解释:当车(策略模式)模(模板方法模式)他爹(迭代模式)责(责任链模式)备(备忘录模式)中介(中介者模式)时,访问者(访问者模式)命令(命令模式)观察者(观察着模式)解释(解释器模式)一下状态(状态模式)。