标签:eem 属性 业务 功能实现 cost 里氏替换原则 完整 while statement
UML和设计模式原则
设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。
使用设计模式的目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。 设计模式使代码编写真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样。可复用、可扩展、可维护
设计模式是GOF(Group Of Four Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides )所著的《设计模式:可复用面向对象软件的基础》一书中所描述的23种经典设计模式,此书奠定了模式在软件行业中的地位,从此人们提到“设计模式”就是默认指“面向对象设计模式”
每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心
特定的问题,特定的解决套路
设计模式分为三大类共23种:
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
Head First设计模式(中文版)HEAD FIRST Jolt震撼大奖headfirst设计模式深入浅出讲清 java设计模式计算机编程自学入门
大话设计模式
统一建模语言(UML,Unified Modeling Language)是面向对象软件的标准化建模语言。UML因其简单、统一的特点,而且能表达软件设计中的动态和静态信息,目前已成为可视化建模语言的工业标准。在软件无线电系统的开发过程中,统一建模语言可以在整个设计周期中使用,帮助设计者缩短设计时间,减少改进的成本,使软硬件分割最优。
建模工具:Rose
COCOMO,英文全称为constructive cost model,中文为构造性成本模型。它是一种精确、易于使用的,基于模型的成本估算方法。
在IDEA中查看类图:
显示细节
双向关联:
C1-C2:指双方都知道对方的存在,都可以调用对方的公共属性和方法。
在GOF的设计模式书上是这样描述的:虽然在分析阶段这种关系是适用的,但我们觉得它对于描述设计模式内的类关系来说显得太抽象了,因为在设计阶段关联关系必须被映射为对象引用或指针。对象引用本身就是有向的,更适合表达我们所讨论的那种关系。所以这种关系在设计的时候比较少用到,关联一般都是有向的。
使用ROSE 生成的代码是这样的:
双向关联在代码的表现为双方都拥有对方的一个指针,当然也可以是引用或者是值。
单向关联:
/**学生类*/
public class Student {
}
/**学校类*/
public class School {
public Student tom;
}
C3->C4:表示相识关系,指C3知道C4,C3可以调用C4的公共属性和方法。没有生命期的依赖。一般是表示为一种引用。
生成代码如下:
单向关联的代码就表现为C3有C4的指针,而C4对C3一无所知。
自身关联(反身关联):
自己引用自己,带着一个自己的引用。
代码如下:
public class Node {
//数据
public int data;
public Node next;
public Node prev;
}
就是在自己的内部有着一个自身的引用。
当类之间有整体-部分关系的时候,我们就可以使用组合或者聚合。
聚合:是一种弱偶合的关联关系。
/**人*/
public class Person {
}
/**引擎*/
public class Engine {
}
/**车*/
public class Car {
/**组合*/
private Engine engine;
public Car(Engine engine){
this.engine=engine;
}
/**聚合*/
public Person driver;
}
组合(也有人称为包容):一般是实心菱形加实线箭头表示,如上图所示,表示的是C8被C7包容,而且C8不能离开C7而独立存在。但这是视问题域而定的,例如在关心汽车的领域里,轮胎是一定要组合在汽车类中的,因为它离开了汽车就没有意义了。但是在卖轮胎的店铺业务里,就算轮胎离开了汽车,它也是有意义的,这就可以用聚合了。在《敏捷开发》中还说到,A组合B,则A需要知道B的生存周期,即可能A负责生成或者释放B,或者A通过某种途径知道B的生成和释放。
/**人*/
public class Person {
/**吃食物*/
public void eat(Food food){
System.out.println("正在吃"+food.name);
}
}
那依赖和聚合\组合、关联等有什么不同呢?
关联是类之间的一种关系,例如老师教学生,老公和老婆,水壶装水等就是一种关系。这种关系是非常明显的,在问题领域中通过分析直接就能得出。
依赖是一种弱关联,只要一个类用到另一个类,但是和另一个类的关系不是太明显的时候(可以说是“uses”了那个类),就可以把这种关系看成是依赖,依赖也可说是一种偶然的关系,而不是必然的关系,就是“我在某个方法中偶然用到了它,但在现实中我和它并没多大关系”。例如我和锤子,我和锤子本来是没关系的,但在有一次要钉钉子的时候,我用到了它,这就是一种依赖,依赖锤子完成钉钉子这件事情。
组合是一种整体-部分的关系,在问题域中这种关系很明显,直接分析就可以得出的。例如轮胎是车的一部分,树叶是树的一部分,手脚是身体的一部分这种的关系,非常明显的整体-部分关系。
上述的几种关系(关联、聚合/组合、依赖)在代码中可能以指针、引用、值等的方式在另一个类中出现,不拘于形式,但在逻辑上他们就有以上的区别。
这里还要说明一下,所谓的这些关系只是在某个问题域才有效,离开了这个问题域,可能这些关系就不成立了,例如可能在某个问题域中,我是一个木匠,需要拿着锤子去干活,可能整个问题的描述就是我拿着锤子怎么钉桌子,钉椅子,钉柜子;既然整个问题就是描述这个,我和锤子就不仅是偶然的依赖关系了,我和锤子的关系变得非常的紧密,可能就上升为组合关系(让我突然想起武侠小说的剑不离身,剑亡人亡...)。这个例子可能有点荒谬,但也是为了说明一个道理,就是关系和类一样,它们都是在一个问题领域中才成立的,离开了这个问题域,他们可能就不复存在了。
泛化关系:如果两个类存在泛化的关系时就使用,例如父和子,动物和老虎,植物和花等。
ROSE生成的代码很简单,如下:
/**学生类*/
public class Student extends Person {
}
引用地址:http://www.cnblogs.com/riky/archive/2007/04/07/704298.html
一个类,只有一个引起它变化的原因。应该只有一个职责。每一个职责都是变化的一个轴线,如果一个类有一个以上的职责,这些职责就耦合在了一起。这会导致脆弱的设计。当一个职责发生变化时,可能会影响其它的职责。另外,多个职责耦合在一起,会影响复用性。例如:要实现逻辑和界面的分离。
一个类只担任一种角色。
下面这个jsp页面就不符合SRP原则,它要担任展示UI与访问数据库两个角色。分层是一种解决办法。
<%@ page contentType="text/html; charset=gb2312" %>
<%@ page language="java" %>
<%@ page import="com.mysql.jdbc.Driver" %>
<%@ page import="java.sql.*" %>
<%
//加载驱动程序
String driverName="com.mysql.jdbc.Driver";
//数据库信息
String userName="root";
//密码
String userPasswd="123";
//数据库名
String dbName="Student";
//表名
String tableName="stu_info";
//将数据库信息字符串连接成为一个完整的url(也可以直接写成url,分开写是明了可维护性强)
String url="jdbc:mysql://localhost/"+dbName+"?user="+userName+"&password="+userPasswd;
Class.forName("com.mysql.jdbc.Driver").newInstance();
Connection conn=DriverManager.getConnection(url);
Statement stmt = conn.createStatement();
String sql="SELECT * FROM "+tableName;
ResultSet rs = stmt.executeQuery(sql);
out.print("id");
out.print("|");
out.print("name");
out.print("|");
out.print("phone");
out.print("<br>");
while(rs.next()) {
out.print(rs.getString(1)+" ");
out.print("|");
out.print(rs.getString(2)+" ");
out.print("|");
out.print(rs.getString(3));
out.print("<br>");
}
out.print("<br>");
out.print("ok, Database Query Successd!");
rs.close();
stmt.close();
conn.close();
%>
开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类,后面的具体设计中我们会提到这点。
美猴王说:"‘皇帝轮流做,明年到我家。‘只教他搬出去,将天宫让于我!"对于这项挑战,太白金星给玉皇大帝提出的建议是:"降一道招安圣旨,宣上界来…,一则不劳师动众,二则收仙有道也。
不要随意修改顶层接口,可以通过继承或其它办法扩展出新的内容。
功能实现应该对扩展开放,对修改关闭,应该通过扩展来实现(应对)变化,而不是通过修改已有的代码来实现变化的内容。
里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。 LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。老鼠的儿子会打洞。
Person tom=new Student();
Object mark=new Teacher();
子类可以覆盖父类的抽象方法,但不能覆盖非抽象方法。
如果需要覆盖父类的非抽象方法,参数的类型必须要比父类的宽松,返回值类型必须要比父类严格。
子类可以拥有自己的成员方法。
在项目中,采用里氏替换原则时,尽量避免子类的“个性”,一旦子类有了“个性”,这个子类和父类之间的关系就难调和,把子类当做父类使用,子类的“个性”被抺杀了,把子类单独作为一个业务来使用,则会让代码间的耦合关系变得扑朔迷离–缺乏类替换的标准。
所谓依赖倒置原则(Dependence Inversion Principle)就是要依赖于抽象,不要依赖于具体。简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模块间的耦合。
实现开闭原则的关键是抽象化,并且从抽象化导出具体化实现,如果说开闭原则是面向对象设计的目标的话,那么依赖倒转原则就是面向对象设计的主要手段。 细节应该依赖抽象,抽象应该依赖抽象,抽象不应该依赖细节
/**人*/
public class Person {
/**吃食物*/
public void eat(Food food){ //依赖具体
System.out.println("正在吃"+food.name);
Person tom=new Student();
Object mark=new Teacher();
}
//Student继承Person
//依赖抽象
public void Show(Person person){
}
//依赖具体
public void Hello(Student student){
}
}
这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。还是一个降低类之间的耦合度的意思,从这儿我们看出,其实设计模式就是一个软件的设计思想,从大型软件架构出发,为了升级和维护方便。所以上文中多次出现:降低依赖,降低耦合。
/**可飞的*/
interface IFlyable{
public void fly();
}
/**下蛋*/
interface ILayeggAble{
public void Layegg();
}
interface IBirdable{
public void fly();
public void Layegg();
}
IBirdable如果被超人(SuperMan)实现则除了要实现fly方法飞还要实现下蛋接方法,超人下蛋不太合适。
合成复用原则就是指在一个新的对象里通过关联关系(包括组合关系和聚合关系)来使用一些已有的对象,使之成为新对象的一部分;新对象通过委派调用已有对象的方法达到复用其已有功能的目的。简言之:要尽量使用组合/聚合关系,少用继承。
为什么叫最少知道原则,就是说:一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。也就是说一个软件实体应当尽可能少的与其他实体发生相互作用。这样,当一个模块修改时,就会尽量少的影响其他的模块,扩展会相对容易,这是对软件实体之间通信的限制,它要求限制软件实体之间通信的宽度和深度。
小结:
1、单一职责原则
二层含义,一是避免相同的职责分散到不同的类中,二是避免一个类承担太多职责。减少类的耦合,提高类的复用性。
2、接口隔离原则
表明客户端不应该被强迫实现一些他们不会使用的接口,应该把胖接口中额方法分组,然后用多个接口代替它,每个接口服务于一个子模块。简单说,就是使用多个专门的接口比使用单个接口好很多。
该原则观点如下:
a,一个类对另外一个类的依赖性应当是建立在最小的接口上
b,客户端程序不应该依赖它不需要的接口方法。
3、开放-关闭原则
open模块的行为必须是开放的、支持扩展的,而不是僵化的。
closed在对模块的功能进行扩展时,不应该影响或大规模影响已有的程序模块。一句话概括:一个模块在扩展性方面应该是开放的而在更改性方面应该是封闭的。
核心思想就是对抽象编程,而不对具体编程。
4、里氏替换原则
子类型必须能够替换掉他们的父类型、并出现在父类能够出现的任何地方。
主要针对继承的设计原则
1,父类的方法都要在子类中实现或者重写,并且派生类只实现其抽象类中生命的方法,而不应当给出多余的,方法定义或实现。
2,在客户端程序中只应该使用父类对象而不应当直接使用子类对象,这样可以实现运行期间绑定。
5、依赖倒置原则
上层模块不应该依赖于下层模块,他们共同依赖于一个抽象(父类不能依赖子类,他们都要依赖抽象类)
抽象不能依赖于具体,具体应该要依赖于抽象。
标签:eem 属性 业务 功能实现 cost 里氏替换原则 完整 while statement
原文地址:https://www.cnblogs.com/group6/p/14341544.html