长宁移动网站建设,做黄页网站要告我,深圳网站建设厂家,网络小程序开发公司这里写目录标题 一、设计模式概述1.1 软件设计模式的产生背景1.2 软件设计模式的概念1.3 学习设计模式的必要性1.4 设计模式分类 二、UML图2.1 类图概述2.2 类图的作用2.3 类图表示法2.3.1 类图表示方法2.3.2 类与类之间关系的表示方法2.3.2.1 关联关系2.3.2.2 聚合关系2.3.2.3… 这里写目录标题 一、设计模式概述1.1 软件设计模式的产生背景1.2 软件设计模式的概念1.3 学习设计模式的必要性1.4 设计模式分类 二、UML图2.1 类图概述2.2 类图的作用2.3 类图表示法2.3.1 类图表示方法2.3.2 类与类之间关系的表示方法2.3.2.1 关联关系2.3.2.2 聚合关系2.3.2.3 组合关系2.3.2.4 依赖关系2.3.2.5 继承关系2.3.2.6 实现关系 三、软件设计原则3.1、开闭原则Open Closed Principle3.2、里氏替换原则Liskov Substitution Principle3.3、依赖倒置原则Dependence Inversion Principle3.4、接口隔离原则Interface Segregation Principle3.5、迪米特法则最少知道原则(Law of Demeter)3.6、合成复用原则Composite Reuse Principle合成复用原则是指尽量先使用组合或者聚合等关联关系来实现其次才考虑使用继承关系来实现。 一、设计模式概述
1.1 软件设计模式的产生背景
设计模式最初并不是出现在软件设计中而是被用于建筑领域的设计中。
1977年美国著名建筑大师、加利福尼亚大学伯克利分校环境结构中心主任克里斯托夫·亚历山大Christopher Alexander在他的著作《建筑模式语言城镇、建筑、构造》中描述了一些常见的建筑设计问题并提出了 253 种关于对城镇、邻里、住宅、花园和房间等进行设计的基本模式。
1990年软件工程界开始研讨设计模式的话题后来召开了多次关于设计模式的研讨会。直到1995 年艾瑞克·伽马ErichGamma、理査德·海尔姆Richard Helm、拉尔夫·约翰森Ralph Johnson、约翰·威利斯迪斯John Vlissides等 4 位作者合作出版了《设计模式可复用面向对象软件的基础》一书在此书中收录了 23 个设计模式这是设计模式领域里程碑的事件导致了软件设计模式的突破。这 4 位作者在软件开发领域里也以他们的“四人组”Gang of FourGoF著称。
1.2 软件设计模式的概念
软件设计模式Software Design Pattern又称设计模式是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。它描述了在软件设计过程中的一些不断重复发生的问题以及该问题的解决方案。也就是说它是解决特定问题的一系列套路是前辈们的代码设计经验的总结具有一定的普遍性可以反复使用。
1.3 学习设计模式的必要性
设计模式的本质是面向对象设计原则的实际运用是对类的封装性、继承性和多态性以及类的关联关系和组合关系的充分理解。
正确使用设计模式具有以下优点。
可以提高程序员的思维能力、编程能力和设计能力。 使程序设计更加标准化、代码编制更加工程化使软件开发效率大大提高从而缩短软件的开发周期。 使设计的代码可重用性高、可读性强、可靠性高、灵活性好、可维护性强。
1.4 设计模式分类
创建型模式
用于描述“怎样创建对象”它的主要特点是“将对象的创建与使用分离”。GoF四人组书中提供了单例、原型、工厂方法、抽象工厂、建造者等 5 种创建型模式。
结构型模式
用于描述如何将类或对象按某种布局组成更大的结构GoF四人组书中提供了代理、适配器、桥接、装饰、外观、享元、组合等 7 种结构型模式。
行为型模式
用于描述类或对象之间怎样相互协作共同完成单个对象无法单独完成的任务以及怎样分配职责。GoF四人组书中提供了模板方法、策略、命令、职责链、状态、观察者、中介者、迭代器、访问者、备忘录、解释器等 11 种行为型模式。
二、UML图
统一建模语言Unified Modeling LanguageUML是用来设计软件的可视化建模语言。它的特点是简单、统一、图形化、能表达软件设计中的动态与静态信息。
UML 从目标系统的不同角度出发定义了用例图、类图、对象图、状态图、活动图、时序图、协作图、构件图、部署图等 9 种图。
2.1 类图概述
类图(Class diagram)是显示了模型的静态结构特别是模型中存在的类、类的内部结构以及它们与其他类的关系等。类图不显示暂时性的信息。类图是面向对象建模的主要组成部分。
2.2 类图的作用
在软件工程中类图是一种静态的结构图描述了系统的类的集合类的属性和类之间的关系可以简化了人们对系统的理解 类图是系统分析和设计阶段的重要产物是系统编码和测试的重要模型。
2.3 类图表示法
2.3.1 类图表示方法
在UML类图中类使用包含类名、属性(field) 和方法(method) 且带有分割线的矩形来表示比如下图表示一个Employee类它包含name,age和address这3个属性以及work()方法。 属性/方法名称前加的加号和减号表示了这个属性/方法的可见性UML类图中表示可见性的符号有三种
表示public
-表示private
#表示protected
属性的完整表示方式是 可见性 名称 类型 [ 缺省值]
方法的完整表示方式是 可见性 名称(参数列表) [ 返回类型]
注意
中括号中的内容表示是可选的也有将类型放在变量名前面返回值类型放在方法名前面 上图Demo类定义了三个方法
method()方法修饰符为public没有参数没有返回值。 method1()方法修饰符为private没有参数返回值类型为String。 method2()方法修饰符为protected接收两个参数第一个参数类型为int第二个参数类型为String返回值类型是int。
2.3.2 类与类之间关系的表示方法
2.3.2.1 关联关系
关联关系是对象之间的一种引用关系用于表示一类对象与另一类对象之间的联系如老师和学生、师傅和徒弟、丈夫和妻子等。关联关系是类与类之间最常用的一种关系分为一般关联关系、聚合关系和组合关系。我们先介绍一般关联。
关联又可以分为单向关联双向关联自关联。 1.单向关联 2.双向关联 3.自关联
2.3.2.2 聚合关系
聚合关系是关联关系的一种是强关联关系是整体和部分之间的关系。
聚合关系也是通过成员对象来实现的其中成员对象是整体对象的一部分但是成员对象可以脱离整体对象而独立存在。例如学校与老师的关系学校包含老师但如果学校停办了老师依然存在。
在 UML 类图中聚合关系可以用带空心菱形的实线来表示菱形指向整体。下图所示是大学和教师的关系图
2.3.2.3 组合关系
组合表示类之间的整体与部分的关系但它是一种更强烈的聚合关系。
在组合关系中整体对象可以控制部分对象的生命周期一旦整体对象不存在部分对象也将不存在部分对象不能脱离整体对象而存在。例如头和嘴的关系没有了头嘴也就不存在了。
在 UML 类图中组合关系用带实心菱形的实线来表示菱形指向整体。下图所示是头和嘴的关系图
2.3.2.4 依赖关系
依赖关系是一种使用关系它是对象之间耦合度最弱的一种关联方式是临时性的关联。在代码中某个类的方法通过局部变量、方法的参数或者对静态方法的调用来访问另一个类被依赖类中的某些方法来完成一些职责。
在 UML 类图中依赖关系使用带箭头的虚线来表示箭头从使用类指向被依赖的类。下图所示是司机和汽车的关系图司机驾驶汽车
2.3.2.5 继承关系
继承关系是对象之间耦合度最大的一种关系表示一般与特殊的关系是父类与子类之间的关系是一种继承关系。
在 UML 类图中泛化关系用带空心三角箭头的实线来表示箭头从子类指向父类。在代码实现时使用面向对象的继承机制来实现泛化关系。例如Student 类和 Teacher 类都是 Person 类的子类其类图如下图所示
2.3.2.6 实现关系
实现关系是接口与实现类之间的关系。在这种关系中类实现了接口类中的操作实现了接口中所声明的所有的抽象操作。
在 UML 类图中实现关系使用带空心三角箭头的虚线来表示箭头从实现类指向接口。例如汽车和船实现了交通工具其类图如图下所示
三、软件设计原则
在软件开发中为了提高软件系统的可维护性和可复用性增加软件的可扩展性和灵活性程序员要尽量根据6条原则来开发程序从而提高软件开发效率、节约软件开发成本和维护成本。
开闭原则里氏代换原则依赖倒转原则接口隔离原则迪米特法则合成复用原则
3.1、开闭原则Open Closed Principle
对扩展开放对修改关闭。在程序需要进行拓展的时候不能去修改原有的代码实现一个热插拔的效果。简言之是为了使程序的扩展性好易于维护和升级。
想要达到这样的效果我们需要使用接口和抽象类。
因为抽象灵活性好适应性广只要抽象的合理可以基本保持软件架构的稳定。而软件中易变的细节可以从抽象派生来的实现类来进行扩展当软件需要发生变化时只需要根据需求重新派生一个实现类来扩展就可以了。
下面以 搜狗输入法 的皮肤为例介绍开闭原则的应用。
【例】搜狗输入法 的皮肤设计。
分析搜狗输入法 的皮肤是输入法背景图片、窗口颜色和声音等元素的组合。用户可以根据自己的喜爱更换自己的输入法的皮肤也可以从网上下载新的皮肤。这些皮肤有共同的特点可以为其定义一个抽象类AbstractSkin而每个具体的皮肤DefaultSpecificSkin和HeimaSpecificSkin是其子类。用户窗体可以根据需要选择或者增加新的主题而不需要修改原代码所以它是满足开闭原则的。
3.2、里氏替换原则Liskov Substitution Principle
里氏代换原则是面向对象设计的基本原则之一。
里氏代换原则任何基类可以出现的地方子类一定可以出现。通俗理解子类可以扩展父类的功能但不能改变父类原有的功能。换句话说子类继承父类时除添加新的方法完成新增功能外尽量不要重写父类的方法。
如果通过重写父类的方法来完成新的功能这样写起来虽然简单但是整个继承体系的可复用性会比较差特别是运用多态比较频繁时程序运行出错的概率会非常大。
下面看一个里氏替换原则中经典的一个例子
【例】正方形不是长方形。
在数学领域里正方形毫无疑问是长方形它是一个长宽相等的长方形。所以我们开发的一个与几何图形相关的软件系统就可以顺理成章的让正方形继承自长方形。 代码如下 长方形类Rectangle
public class Rectangle {private double length;private double width;public double getLength() {return length;}public void setLength(double length) {this.length length;}public double getWidth() {return width;}public void setWidth(double width) {this.width width;}
}
正方形类Square
由于正方形的长和宽相同所以在方法setLength和setWidth中对长度和宽度都需要赋相同值。
public class Square extends Rectangle {public void setWidth(double width) {super.setLength(width);super.setWidth(width);}public void setLength(double length) {super.setLength(length);super.setWidth(length);}
}
类RectangleDemo是我们的软件系统中的一个组件它有一个resize方法依赖基类Rectangleresize方法是RectandleDemo类中的一个方法用来实现宽度逐渐增长的效果。
public class RectangleDemo {public static void resize(Rectangle rectangle) {while (rectangle.getWidth() rectangle.getLength()) {rectangle.setWidth(rectangle.getWidth() 1);}}//打印长方形的长和宽public static void printLengthAndWidth(Rectangle rectangle) {System.out.println(rectangle.getLength());System.out.println(rectangle.getWidth());}public static void main(String[] args) {Rectangle rectangle new Rectangle();rectangle.setLength(20);rectangle.setWidth(10);resize(rectangle);printLengthAndWidth(rectangle);System.out.println();Rectangle rectangle1 new Square();rectangle1.setLength(10);resize(rectangle1);printLengthAndWidth(rectangle1);}
}我们运行一下这段代码就会发现假如我们把一个普通长方形作为参数传入resize方法就会看到长方形宽度逐渐增长的效果当宽度大于长度,代码就会停止这种行为的结果符合我们的预期假如我们再把一个正方形作为参数传入resize方法后就会看到正方形的宽度和长度都在不断增长代码会一直运行下去直至系统产生溢出错误。所以普通的长方形是适合这段代码的正方形不适合。 我们得出结论在resize方法中Rectangle类型的参数是不能被Square类型的参数所代替如果进行了替换就得不到预期结果。因此Square类和Rectangle类之间的继承关系违反了里氏代换原则它们之间的继承关系不成立正方形不是长方形。
如何改进呢此时我们需要重新设计他们之间的关系。抽象出来一个四边形接口(Quadrilateral)让Rectangle类和Square类实现Quadrilateral接口 3.3、依赖倒置原则Dependence Inversion Principle
高层模块不应该依赖低层模块两者都应该依赖其抽象抽象不应该依赖细节细节应该依赖抽象。简单的说就是要求对抽象进行编程不要对实现进行编程这样就降低了客户与实现模块间的耦合。
3.4、接口隔离原则Interface Segregation Principle
客户端不应该被迫依赖于它不使用的方法一个类对另一个类的依赖应该建立在最小的接口上。
3.5、迪米特法则最少知道原则(Law of Demeter)
迪米特法则又叫最少知道原则。
只和你的直接朋友交谈不跟“陌生人”说话Talk only to your immediate friends and not to strangers。
其含义是如果两个软件实体无须直接通信那么就不应当发生直接的相互调用可以通过第三方转发该调用。其目的是降低类之间的耦合度提高模块的相对独立性。
迪米特法则中的“朋友”是指当前对象本身、当前对象的成员对象、当前对象所创建的对象、当前对象的方法参数等这些对象同当前对象存在关联、聚合或组合关系可以直接访问这些对象的方法。
3.6、合成复用原则Composite Reuse Principle合成复用原则是指尽量先使用组合或者聚合等关联关系来实现其次才考虑使用继承关系来实现。
通常类的复用分为继承复用和合成复用两种。
继承复用虽然有简单和易实现的优点但它也存在以下缺点
继承复用破坏了类的封装性。因为继承会将父类的实现细节暴露给子类父类对子类是透明的所以这种复用又称为“白箱”复用。子类与父类的耦合度高。父类的实现的任何改变都会导致子类的实现发生变化这不利于类的扩展与维护。它限制了复用的灵活性。从父类继承而来的实现是静态的在编译时已经定义所以在运行时不可能发生变化。
采用组合或聚合复用时可以将已有对象纳入新对象中使之成为新对象的一部分新对象可以调用已有对象的功能它有以下优点
它维持了类的封装性。因为成分对象的内部细节是新对象看不见的所以这种复用又称为“黑箱”复用。对象间的耦合度低。可以在类的成员位置声明抽象。复用的灵活性高。这种复用可以在运行时动态进行新对象可以动态地引用与成分对象类型相同的对象。