需求分析与设计总结

时间:2024.4.20

OOD原理:

1.       开放封闭原理 (The Open-Closed Principle 、OCP)

2.       里氏代换原理 (Liskov Substitution Principle, LSP)

3.       依赖倒转原理 (Dependence Inversion Principle, DIP)

4.       单一职责原理 (Single Responsibility Principle,SRP)

5.       接口隔离原则 (Interface Segregation Principle, ISP)

6.       合成复用原则 (Composite Reuse Principle, CRP)

7.       迪米特法则 ( Law of Demeter, LoD )

一.             LSP 里氏替换原则(敏捷第十章,编程导论p53

1.什么是里氏替换原则:

(1).子类型是一个父类型(如果对于类型SmartDog的任何一个对象(在源代码中为引用变量或引用值)s,存在着一个类型Dog 的对象d ,在所有的使用了Dog的程序P中,如果用sd替换d后P的行为不变,则SmartDog是Dog的子类型(subtype)。)

(2).子类型(必须)能够替代其父类型(LSP强调了子类型必须具备替换属性,即在一个软件系统中,基类出现的所有地方必须都能够被子类型替代。)

2.继承的分类:

 (1)特化(specialization)继承

(特化继承的基本表现是

?  子类直接获得父类的方法

?  或者改写父类的(已经实现的)方法体。

特化继承又称实现继承(implementation inheritance),或者说以父类的代码复用为目的的继承。)

 (2)扩展(extension)继承

           (扩展继承的基本表现是子类增加新的功能但是不改写继承于父类的方法)

 (3)协议(Specification、规范)继承

            (通常称为接口继承,指对抽象方法的继承。

对抽象方法的实现称为延迟实现,而改写是一种实现继承 )

(4)多重继承(multiple inheritance )

            (子类型继承多个父类型。Java对于多重继承作出如下规定:

²  类只能继承一个父类,同时

²  一个类可以实现(使用关键字implements)多个接口。

²  一个接口可以继承(使用关键字extends)多个接口。)

3.违反LSP原则的代码

 ◇ 不应该在代码中出现if/else之类对子类类型进行判断的条件。以下代码就违反了LSP定义。

view plaincopy to clipboardprint?

01.if (obj typeof Class1) { 

02.    do something 

03.} else if (obj typeof Class2) { 

04.    do something else 

05.} 

if (obj typeof Class1) {

    do something

} else if (obj typeof Class2) {

    do something else

}

◇ 子类应当可以替换父类并出现在父类能够出现的任何地方。

经典违背例子:长方形与正方形

1.     //长方形类:   

2.    public class Rectangle{  

3.      ...  

4.      setWidth(int width){  

5.          this.width=width;  

6.      }  

7.      setHeight(int height){  

8.          this.height=height  

9.      }  

10.   }  

11.   //正方形类:   

12.   public class Square{  

13.     ...  

14.     setWidth(int width){  

15.         this.width=width;  

16.         this. height=width;  

17.     }  

18.     setHeight(int height){  

19.         this.setWidth(height);  

20.     }  

21.   }  

22.   //例子中改变边长的方法:   

23.   public void resize(Rectangle r){  

24.     while(r.getHeight()<=r.getWidth){  

25.         r.setHeight(r.getWidth+1);  

26.     }  

27.   }  

4.哪些不遵循LSP原则

 鸵鸟——鸟

正方形——矩形

鲸鱼——鱼

5接口的一致性问题(接口的实现与分离又称为parnas原则)

子类要继承父类的接口    接口的思想就是“封装隔离”。

通常用接口来定义实现类的外观,也就是实现类的行为定义,用来约束实现类的行为。接口就相当于一份契约,根据外部应用需要的功能,约定了实现类应该要实现的功能,但是具体的实现类除了实现接口约定的功能外,还可以根据需要实现一些其它的功能,这是允许的,也就是说实现类的功能包含但不仅限于接口约束的功能。

6.为什么实现继承是有害的

(1)脆弱的基类(该问题指在允许对超类或多个超类的实现进行演化的同时,使其子类仍然有效并可用。除非将公共接口声明为不可变,或者至少要避免对我们控制范围之外的超类进行实现继承,否则很难控制脆弱的基类问题)

(2)重载和回调(只要有对象间的引用就可能有回调)

(3)多重实现继承(多重实现继承允许实现片段的合并。它并没有给实现继承带来更多的危害,只是放大了由脆弱的基类,重载和回调所引发的问题)

二.抽象依赖原则

   1.抽象依赖原则是什么

    为了应对需求变化,代码中要尽可能地使用(依赖)抽象类型,而非具体类

   2.开放封闭原则(ocp)

   一个软件实体(类、模块、函数等等)应对扩展开放,对修改关闭  如下解释:

?     open for extension 可扩展(对扩展是开放的):

?    模块的行为、系统的功能可以被扩展,在应对需求改变或需要满足新的应用需求时,我们可以让模块以不同的方式工作。

?    语言上:继承、多态

?    前提:LSP

?    closed for modification 不可修改(对修改是封闭的):

?    模块的源代码是不可改动的。任何人,包括类创建者,都不许修改模块的源代码。

对模块行为的扩展,不会导致模块的源代码变化

   3.针对接口编程

   不将变量声明为某个特定的具体类的实例对象,而是让它遵从抽象类所定义的接口

?       用户模块 依赖于抽象类/接口,不要依赖于具体类。

?    应该在必须耦合的模块之间建立抽象耦合。

?    任何对象变量都不应该持有指向具体类的指针或者引用。

?    任何类都不应该从具体类派生。[注意:这里指你设计的类层次]

?    任何方法都不应该改写其任何基类中已经实现的方法。[基类的方法应该是抽象方法,否则基类应该是具体类]。

   针对接口编程,而不是针对实现编程(接口interface Vs 实现implementation:

接口描述该系统是设计出来干什么的,是该抽象的用户必须理解的情况/视图。

实现,完成该抽象的操作。)

   接口与实现是分离的。

   4.代码同构(静态工厂,工厂方法,依赖注入,反射机制)

  

   5.创建型模式的意图

提供一个接口,让该接口负责创建一系列“相关或者相互依赖的对象”,无需指定它们具体的类。  

 

   6.使用策略模式重构相应代码 (笔记P14)

   7.重构三模式 (笔记P14)

(1)策略

源代码:swicth(case)

  case 1:

    do1();

    break;

  case 2:

    do2();

    break;

  .....

do1(){}

do2(){}

策略模式代码:interface FactionFace{

  void do();
}

class FactionFaceImpl1 : FactionFace{

  public void do(){}
}

class FactionFaceImpl2 : FactionFace{

  public void do(){}
}

Dictionary<int, FactionFace> dict = new Dictionary<int, FactionFace>();

dict.Add(1,new FactionFaceImpl1());

dict.Add(2,new FactionFaceImpl2());

int parm = 0;

if(dict.ContainKey(parm)){

  dict[parm].do();
}

(2)状态

(3)静态工厂

简单工厂模式(Simple Factory Pattern)又称为静态工厂方法(Static Factory Method)模式。角色包含:

?       Factory:工厂角色

?       Product:抽象产品角色

?       ConcreteProduct:具体产品角色

三.Parnas原则

1. (1)什么是parnas原则

  (模块的)接口基本上由子程序的名称和参数的名称与类型组成

   使用者应该遵循——开发一个模块时,仅需要知道其他模块的接口

   开发者——给用户提供接口

 (2)什么是定义良好的接口(前置和后置条件)

   一个定义良好的接口,方法名应该命名规范,简洁而有暗示性;方法签名包含各种可能的重载要求。更重要的是,应该是完备的方法说文档。

  前置条件:前置条件是用户调用该方法时必须满足的条件。为了方法能够执行并产生预期结果,前置条件必须为true。通常前置条件对传递给方法的参数提了要求。

  后置条件:是方法执行完毕后能够确保达到某一状态。通常后置条件说明了返回值或方法的副作用。每一个方法都有后置条件,除非它是空方法——不对程序产生任何影响。

2.从parnas出发,java接口和它的实现类(纯接口,不涉及抽象)

  Java接口是定义abstract方法和静态命名常量的java程序单元。定义接口:

      Public interface A{

         String STR=”hello”;

         Void foo();

         Int X(int i);

      } //interface声明一个新接口

  口的实现类:即接口的子类,是实现接口的类。

3.什么是信息隐藏

  将不需要暴露出来的数据和行为,屏蔽在用户程序员的视线之外,这一方法叫做信息隐藏。

4从parnas出发阐述封装的概念(把类接口暴露出来)(按parnas原则,用户?与客户?)

  是指将对象的全部属性和方法包裹起来,形成一个不可分割的整体。类途径/通过有限的接口与外界交互。封装的主要工作是使用访问修饰符限定类的接口。

5.事件驱动编程

  当一个GUI程序启动后,JVM显示最初的界面图形(一个applet或窗口,以及各种组件的形状),然后处于无限循环的等待状态。一旦用户的某一动作如单击按钮或鼠标移动发生时,JVM经过一系列底层运作找到并执行相应的代码。

6.通过代码演示设计不变类

public final class String{

       /** Cache the hash code for the string */

private int hash; // Default to 0

      public int hashCode() {

int h = hash;

if (h == 0) {

       // compute the value

            hash = h; // cache the value
       }
        return h;
    }
}

四.回调

 1.单向依赖

(无环依赖:在组件的依赖关系中不允许存在环)

  分层架构遵循单向依赖原则:除(不依赖其他模块的)公共模块如model模块,可被各层调用外,一个层的模块只依赖于同一层或下层的模块。

★单向依赖原则:依赖应该是单向的,不得循环或相互依赖。

 2.使用类图解释java中回调机制的内部机制   callback

一个回调函数/方法(简称回调/ callback)是上层模块定义的,将被下层模块(反过来)调用的方法。

下层模块Server不知道上层定义的接口也不应该直接调用上层接口。

 

回调方法是某个上层模块定义的功能接口,但是所有上层模块都不会直接调用它,而设计它的目的就是为了下层模块的反向调用

回调通常指可以被作为参数传递给其他代码的可执行代码块,或者一个可执行代码的引用

 3.讨论设计模式中好莱坞法则IoC(代码解释)

 Package API.event;

Import java.util.List;

Import java.util.ArrayList;

Public class Server2{

Private List<IXxx> listeners=new ArrayList<IXxx>();  //电话薄

Public void register(IXxx listener){

  Listeners.add(listener);

}

Public void sthHappened(){     //某种状态发生改变

  For(IXxx x:  listeners){

   X.callback(10);        //通知所有已登记的演员

}

     }

  }

//上层模块

  Package API.event;

  Class TestCallBack2{

     Public static void test{

     Server2 s=new Server2();

     s.register( new Client());

     s.ergister( new Client());

     s.sthHappened();        //这里由上层模块触发事件的发生

}

 }

认识好莱坞法则是什么don`t call me,i`ll call you

   You——是谁  指上层模块

4.DIP定义(依赖倒置原则),意义

(1)高层模块不应该依赖于低层模块。二者都应该依赖于抽象

(2)抽象不应该依赖于细节。细节应该依赖于抽象。

 意义:是框架设计的核心原则

五.

 1.为什么在分析设计阶段要忘掉关系型数据库   介绍nosql 和ORM

?    分析、设计阶段,我们仅仅知道类的属性。

?    如果类一一对应关系型数据库中的表,我们就不需要考虑关系型数据库。注意Hibernate(Java)和NHibernate(C#)的主要作用就是不需要设计数据库。

?    仓储模式将数据访问封装,仅仅数据访问层才了解数据库。

?    我们使用NoSQL——MongoDB

2.变化与设计(敏捷第七章 设计臭味)

1.僵化性:软件难以修改。修改花费的代价巨大;   

2.脆弱性:一个修改可能引发很多意想不到的问题;  

3.顽固性:设计中包含了对其他系统有用的部分,但是把这部分从系统中分离出来所需要的努力和风险非常之大;   

 4.粘滞性:当面临修改时,开发人员有两类修改方法:一是保持设计;而是破坏设计(拼凑方法。当可以保持系统设计的方法比破坏设计的方法更难应用时,系统就有很高的粘滞性;     5.不必要的重复:是忽略抽象的结果;    

6.不必要的复杂性:系统包含了当前没有用的组成部分;  

7.晦涩性:模块难以理解,代码晦涩难懂。

3.耦合

耦合是不同模块之间相互依赖(连接、互联)程度的度量。

4.迪米特法则LoD

   法则说明,需要具体类-具体类发生耦合时,“只和自己最亲密的朋友说话,不和陌生人说话 ”。

最少知识原则:每一个单元应当对其它单元有尽可能少的了解:仅仅了解那些和当前单元有“紧密”关系的单元。

最亲密的朋友:

?    类的成员(这是必须了解的,可能有多个亲密的成员朋友)

?    方法的参数对象(如yy)

?    方法中(不得不)创建的(局部)对象。

?    非最亲密的朋友,可以通过最亲密的朋友去转发消息。

迪米特法则的主要用意是控制信息的过载,在将其运用到系统设计中应注意以下几点:

?    1) 在类的划分上,应当创建有弱耦合的类。类之间的耦合越弱,就越有利于复用。

?    2) 在类的结构设计上,每一个类都应当尽量降低成员的访问权限。一个类不应当public自己的属性,而应当提供取值和赋值的方法让外界间接访问自己的属性。

?    3) 在类的设计上,只要有可能,一个类应当设计成不变类。

?    4) 在对其它对象的引用上,一个类对其它对象的引用应该降到最低。

5.合成优先

6.忘掉结构化:

?    不要使用结构化和面向对象像结合的办法。

?    从用例分析活动中识别类的责任、属性和交互。

?    建立领域对象的关系。

更多相关推荐:
需求分析总结报告 [模板]

文件编号:MAC-SWE-TMP-17密级:■保密□通用需求分析总结报告[模板]RequirementAnalysisReport[Template]本程序属MAC公司所有,未经书面许可,不得以任何形式复印或传…

项目需求分析总结

需求分析是项目开发的基础,基础打的牢不牢直接关系到后面所有的工作,是项目实施成败的关键总体上说,我们的需求分析是做了,但是做得很不够,我们做的需求只解决了我们能做出这样的项目,但是没有解决这样的项目是不是真就是…

需求分析报告

需求分析报告1引言在市场经济中进销存管理是企业运作的重要环节随着企业规模的发展壮大商品数量急剧增加有关商品的各种信息量也成倍增加企业需要实时动态地对商品的各种信息进行统计分析为了便好地增加业务量另外不少企业通过...

关于需求分析的总结报告

关于需求分析的总结报告在学习了第四章的需求获取之后做出以下总结这部分主要强调了在优秀的软件工程中抽象和建模的关键原则。使用模型来从已有的需求中梳理出误解和遗漏的的细节并与他人沟通需求。讨论了需求的不同资源和不同…

需求分析总结报告

密级保密需求分析总结报告组长李威20xx118161组员胡立柱20xx118168徐新祥20xx118174张浩20xx118175范浩楠20xx118176王博20xx1181771密级保密一引言为使项目能够...

需求分析思路总结

需求分析思路需求说明书应该满足两方面阅读群体想了解宏观需求的领导和需要了解细节的技术员都合适在写需求说明书时应该注意两个问题1最好为每个需求注释这样可让程序员了解需求的本质以便选用最合适的技术来实现此需求2需求...

做需求分析一点心得

20xx-09-16作者:Neo.Yan来源:Neo.Yan的blog1、需求分析前的准备在软件开发过程中,需求分析可以说是核心任务之一,就像一支将要远航的船队,要在指定时间内到达目录地,他们需要一条正确的航线…

如何做需求分析

如何做需求分析这段时间我做了两个大项目其中一个项目算是商业模式上和使用规范上的调整另一个项目是之前功能的重做为什么重做我下面会说到关于需求分析我认为把需求抽象成产品功能花费的时间占到了软件开发周期的40产品设计...

物流管理系统的需求分析报告

物流管理系统需求分析说明书自动化学院08网络3班陈伟亮陈晓铎陈泽满何文俊1引言错误未定义书签11编写目的错误未定义书签12背景113定义12任务概述121目标123需求特点33功能需求34系统分析441系统数据...

软件需求分析师工作内容

软件需求分析师工作内容小伙伴儿们听说过软件需求分析师吗今天乔布简历小编想和大家聊聊软件需求分析师的工作内容呢关键词软件需求分析师的工作内容所谓软件需求分析师就是那些对公司设计的软件进行相关需求文档的撰写合理分析...

方差分析总结

方差分析总结,内容附图。

多元回归分析总结分析

第十二章多元回归分析在许多实际问题中影响因变量的因素有一个时我们用一元回归分析解决问题但是影响因变量的因素往往有多个此时问题就上升到了一个因变量同多个自变量的多元回归问题当因变量与自变量之间为线性关系时我们称之...

需求分析总结(37篇)