主要内容
详细内容
UML
概述
UML(United Modeling Language)是一种基于面向对象的可视化建模语言,是一种以可视化观点来看程序系统,并将格式和设计重点直接写下来的表现形式;UML采用一组形象化的图形符号作为建模语言,使用这些符号可以形象的描述系统的各个方面。
静态模型图
动态模型图
关系
面向对象的设计模式
单一职责原则:
一个类只有一个引起它变化的原因,如果一个类有一个以上的职责,这些职责就耦合在了一起。当一个职责发生变化时,可能会影响其它的职责。多个职责耦合在一起,会影响复用性。
开闭原则:
软件实体(类、模块、函数等)应该是可扩展的,但是不可修改。
遵循开发-封闭原则设计的两个主要特征:
(1)对于扩展是开放的;
(2)对于更改是封闭的;
(3)好处:
i. 可复用性好:软件完成之后,仍然可以对软件进行扩展,加入新的功能,非常灵活。因此,这个软件系统就可以通过不断地增加新的组件来满足不断变化的需求;
ii. 可维护性好:由于对于已有的软件系统的组件,特别是它的抽象底层不去修改,因此,我们不用担心软件系统中原有组件的稳定性,这就使变化中的软件系统有一定的稳定性和延续性。
里氏代换原则:
(1)子类必须能够替换掉它们的基类型;
(2)里氏代换原则是对开闭原则的补充;
(3)在进行设计的时候,尽量从抽象类继承,而不是从具体类继承。
依赖倒置原则:
(1)高层模块不应该依赖于底层模块,二者都应该依赖于抽象;
(2)抽象不应该依赖于细节,细节应该依赖于抽象;
(3)Hollwood原则:“Don’t call us,we’ll call you”.程序中所有的依赖关系都应该终止于抽象类和接口和接口针对接口而非实现编程。
(4)依赖于抽象的启发式规则:
i. 任何变量都不应该持有一个指向具体类的指针或者引用;
ii. 任何类都不应该从具体类派生;
iii. 任何方法都不应该覆写任何基类中已经实现了的方法。
接口隔离原则:
(1)使用多个专门的接口比使用单一的总接口要好;
(2)一个类对另外一个类的依赖性应当是建立在最小的接口上的;
(3)一个接口代表一个角色,不应当将不同的角色交给一个i饿接口;
(4)不应该强迫客户依赖于它们不同的方法;接口属于客户,不属于它所在的类层次结构;
(5)满足接口隔离原则,调用者只能访问它自己的方法,不能访问到不应该访问的方法。
合成/聚合复用原则:
(1)合成(Composition)和聚合(Aggregation)都是关联(Association)的特殊种类。聚合表示整体和部分的关系,表示“拥有”;合成则是一种更强的“拥有”,部分和整体的生命周期都是一样;
(2)在OOD中,有两种基本的方法可以实现复用:合成/聚合、继承。
迪米特法则:
(1)可以简单的说则:talk only to your immediate friends
(2)一个软件实体应当尽可能少的与其它实体发生相互作用。每一个软件单位对其他的软件单位都只有最少的只是,而且局限于那些与本单位密切相关的软件单位;
(3)其初衷在于降低类之间的耦合。
类、对象和方法高效设计原则
类与对象高效设计原则:
(1)避免创建重复对象;
(2)消除过期的对象引用;
(3)避免使用终结函数;
(4)为所有到处API的元素编写文档注释;
(5)使类和成员的可访问能力最小化;
(6)复合优于继承:继承是复用的有力手段但不是最佳工具
i. 对普通类跨包继承,是非常危险的;
ii. 与方法调用不同,继承打破了封装性;
iii. 使用复合的方式可以完全取代继承的复用;
iv. 符合类不依赖与原有类的实现细节,原有类修改不会影响到符合类。
(7)接口优先于抽象类:
a) 抽象类只允许单继承,作为类型定义受到了极大限制;
b) 已有的类可以很容易更新,实现新的接口,并使得安全的增强一个类的功能称为可能。
(8)定义内部类:优先考虑静态成员类。
方法的高效设计:
(1)谨慎选择方法的名字,要简洁易懂;
(2)避免使用过长的参数列表;
(3)对于参数类型,优先使用接口而不是类;
(4)返回零长度数组而不是null;
(5)将局部变量的作用域最小化;
(6)第一次使用方法的地方声明;
(7)每一个局部变量的声明都应该包含一个初始化表达式;
(8)For循环优先于while循环;
(9)方法小而集中。
面向对象设计的经验:
谁拥有数据,谁就对外提供操作这些数据的方法。
(1)两块石头磨成一把石刀,石刀可以砍树,砍成木材,木材做成椅子;实现代码如下所示:
//两块石头磨成一把石刀,石刀可以砍树,砍成木材,木材做成椅子
//石头类
class Stone
{
}
class StoneKnife
{
public Stone first;
public Stone second;
StoneKnife stoneKnife = KnifeFactory.createKnife(first,second);
}
//树类
class Tree
{
}
//材料类
class Material
{
}
//椅子类
class Chair
{
public Material material;
Chair chair = ChairFactory.makeChair(material);
}
class KnifeFactory
{
public void createKnife(Stone first,Stone second)
{
}
}
class ChairFactory
{
public void makeChair(Material material)
{
}
}
(2)球从一根绳子的一段移动到了另一端;实现代码如下所示:
//球从一根绳子的一段移动到了另一端
//绳子类
class Rope
{
//开始位置
private Point start;
//结束位置
private Point end;
public Rope(Point start,Point end)
{
this.start = start;
this.end = end;
}
public Point nextPoint(Point currentPoint)
{
/*
通过两点一线的数学公式可以计算出当前点的下一个点;
如果当前点是终止点,则返回null,
如果当前点不是线上的点,则抛出异常。
*/
}
}
//球类
class Ball
{
private Rope rope;
//当前位置
private Point currentPoint;
public Ball(Rope rope,Point startPoint)
{
this.rope = rope;
this.currentPoint = startPoint;
}
//移动方法
public void move()
{
currentPoint = rope.nextPoint(currentPoint);
System.out.println("小球移动到了" + currentPoint);
}
}