面向对象 归纳分析 (设计模式,uml)

本文概述了面向对象编程中的UML图(如用例图、类图和序列图),重点讲解了用例、系统边界、关系、继承与实现等概念。同时介绍了策略模式、观察者模式、工厂模式等常见设计模式的应用和意义。

面向对象考点大纲

1.UML图

  • User case diagram

  • Class model diagram

  • Sequence diagram

    use case diagram

  • Actor:用户或者一些事件的代理人的特征比如time或者temporature

  • use case:对系统功能的描述

  • System boundary

  • 关系

    • include:指的是小用例被包含在大用例的功能之中(大的指向小的)
      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jv0eQ4de-1616949044484)(assets/image.png)]

    • entend:小用例拥有大用例的扩展功能,不被包含在大用例中(小的指向大的)
      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sdetdnl0-1616949044486)(assets/image%202.png)]

    • generalization:一般化是指一个较一般的分类器和一个较具体的分类器之间的分类关系。特定分类器的每个实例也是一般分类器的间接实例。因此,具体分类器继承了较一般分类器的特征。
      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o5M0cU1u-1616949044487)(assets/image%202%203.png)]

      (延长租书时间为什么不是借书的扩展?因为这是用户可以单独发起的事件,用户选择延长时间的时候并不需要借书)

      class diagram

      表示方法:

  • public +

  • private -

  • protected #

  • package ~

  • 关系

    • 依赖dependent:
      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HvJHwDKX-1616949044488)(assets/image%202%203%204.png)]

      最弱的关系,一个类的方法中用到了另一个类

    • 关联 association:
      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4wKFWk1K-1616949044489)(assets/image%202%203%204%205.png)]

      A中有B的实例,但B中没有A的实例

    • 双向关联
      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GiHxAQvE-1616949044489)(assets/image%202%203%204%205%206.png)]

    • 聚合关系 aggregation
      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xZNzAbg5-1616949044490)(assets/image%202%203%204%205%206%207.png)]

      是关联关系的一种,和关联关系在语法上无法区分,在语意上有区分,聚合关系是一种整体和部分的关系.而关联关系是一种拥有的关系

    • 组合关系 composition
      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gOEnbbrF-1616949044491)(assets/image%202%203%204%205%206%207%208.png)]

      也是关联关系的一种,但是更加强的依赖,也是整体和部分的关系,但是整体消亡的时候,部分也不复存在

    • Inheritance and Generalization(继承)
      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SrudSea2-1616949044492)(assets/image%202%203%204%205%206%207%208%209.png)]

    • Realization(实现)
      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F6sr7CMv-1616949044492)(assets/image%202%203%204%205%206%207%208%209%2010.png)]实现一个接口类

Sequence Diagram

组成对象:

  • actor:系统外部的对象
  • object:一个类或者是一个对象
  • lifeline:从actor或者object引出的线
  • activation:一个task被激活的时期

消息:

  • Synchronous Message (同步消息):用实心线加箭头表示表示一个sender发送了一个消息并且正在等待回复

  • Reply Message (返回消息):虚线加箭头

  • Asynchronous Message (异步消息):单箭头,不需要等待回复

  • 通过消息创建对象[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kvRuFRkf-1616949044493)(assets/image%202%203%204%205%206%207%208%209%2010%2011%2012.png)]

  • 通过消息销毁对象[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-85sds5ga-1616949044494)(assets/image%202%203%204%205%206%207%208%209%2010%2011.png)]

  • 自关联消息[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-idmpec9t-1616949044494)(assets/image%202%203%204%205%206%207%208%209%2010%2011%2012%2013.png)]

框架

  • loop[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8iunPY9T-1616949044495)(assets/image%202%203%204%205%206%207%208%209%2010%2011%2012%2013%2014.png)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FkOsVYid-1616949044496)(assets/image%202%203%204%205%206%207%208%209%2010%2011%2012%2013%2014%2015.png)]

  • if[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ObhJOPpT-1616949044496)(assets/image%202%203%204%205%206%207%208%209%2010%2011%2012%2013%2014%2015%2016.png)]

  • if…else…[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T6kBVa0w-1616949044497)(assets/image%202%203%204%205%206%207%208%209%2010%2011%2012%2013%2014%2015%2016%2017.png)]

2.策略模式

定义了算法族,把不同的算法分别封装起来,比如说鸭子类,我们把鸭子的飞行方法独立成一个类,或者说在这里我们独立成一个接口,然后去根据飞行接口实现不同的飞行方式,再让这些鸭子去继承这些实现,从而达到代码的重用和方便更改.另外我们还在鸭子类中设计setfly(),以便随时更改鸭子的飞行方式.其中setfly()在超类中定义即可.

3.观察者模式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zEw5A2dv-1616949044498)(assets/image%202%203%204%205%206%207%208%209%2010%2011%2012%2013%2014%2015%2016%2017%2018.png)]

subject类:

  • field:观察者列表,观察到的数据(温度,天气等等)
  • func:注册,取消,通知,更新数据

observer类:

  • filed:要接受的数据,subject实例(通过这个注册)
  • func:update

3.工厂模式

简单工厂

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S7E6fx7F-1616949044498)(assets/image%202%203%204%205%206%207%208%209%2010%2011%2012%2013%2014%2015%2016%2017%2018%2019.png)]

缺点是当我们要想加入一个新的品种时,我们不得不修改工厂的代码,这违反了开闭原则.

工厂方法模式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WyJaItTF-1616949044499)(assets/image%202%203%204%205%206%207%208%209%2010%2011%2012%2013%2014%2015%2016%2017%2018%2019%2020.png)]

当我们要加入一个新的品种时,我们只需要加一个新的子类即可.

抽象工厂模式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YOacOaTJ-1616949044499)(assets/image%202%203%204%205%206%207%208%209%2010%2011%2012%2013%2014%2015%2016%2017%2018%2019%2020%2021.png)]

4.单例模式

  1. 懒汉式,线程不安全
    是否 Lazy 初始化:是
    是否多线程安全:否
    实现难度:易
    描述:这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程。因为没有加锁 synchronized,所以严格意义上它并不算单例模式。
    这种方式 lazy loading 很明显,不要求线程安全,在多线程不能正常工作。

    public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  
    
    public static Singleton getInstance() {  
    if (instance == null) {  
        instance = new Singleton();  
    }  
    return instance;  
    }  
    }
    
  2. 懒汉式,线程安全
    是否 Lazy 初始化:是
    是否多线程安全:是
    实现难度:易
    描述:这种方式具备很好的 lazy loading,能够在多线程中很好的工作,但是,效率很低,99% 情况下不需要同步。
    优点:第一次调用才初始化,避免内存浪费。
    缺点:必须加锁 synchronized 才能保证单例,但加锁会影响效率。
    getInstance() 的性能对应用程序不是很关键(该方法使用不太频繁)。

    public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  
    public static synchronized Singleton getInstance() {  
    if (instance == null) {  
     instance = new Singleton();  
    }  
    return instance;  
    }  
    }
    
  3. 饿汉式
    是否 Lazy 初始化:否
    是否多线程安全:是
    实现难度:易
    描述:这种方式比较常用,但容易产生垃圾对象。
    优点:没有加锁,执行效率会提高。
    缺点:类加载时就初始化,浪费内存。
    它基于 classloader 机制避免了多线程的同步问题,不过,instance 在类装载时就实例化,虽然导致类装载的原因有很多种,在单例模式中大多数都是调用 getInstance 方法, 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化 instance 显然没有达到 lazy loading 的效果。

    public class Singleton {  
    private static Singleton instance = new Singleton();  
    private Singleton (){}  
    public static Singleton getInstance() {  
    return instance;  
    }  
    }
    
  4. 双检锁/双重校验锁(DCL,即 double-checked locking)
    JDK 版本:JDK1.5 起
    是否 Lazy 初始化:是
    是否多线程安全:是
    实现难度:较复杂
    描述:这种方式采用双锁机制,安全且在多线程情况下能保持高性能。
    getInstance() 的性能对应用程序很关键。

    public class Singleton {  
    private volatile static Singleton singleton;  
    private Singleton (){}  
    public static Singleton getSingleton() {  
    if (singleton == null) {  
     synchronized (Singleton.class) {  
     if (singleton == null) {  
         singleton = new Singleton();  
     }  
     }  
    }  
    return singleton;  
    }  
    }
    

    5.命令模式

    把方法调用封装起来
    在这里插入图片描述
    其中invoker可以在某个时候调用execute以执行命令
    每一个receiver对象都包含一系列的动作,我们把他封装成一个command,在command里,我们只要调用execute就可以执行这些方法.
    其中的setCommand()可以把这些个command绑定到某个slot上,我们只需要按下这个slot,这个slot就会调用这个command,然后我们可以调用这个command.execute(),这个方法又会调用recieiver去执行其中的一系列的方法.

    6.适配器模式

    将一个类的接口转换成另一个接口.适配器让原本接口不兼容的类可以合作.

  5. 对象适配器
    在这里插入图片描述

    其中adapter会调用adaptee作为构造器,通过adaptee的方法去伪装实现Target的方法.

  6. 类适配器
    在这里插入图片描述

7.装饰者模式

让接口变得更简单!

  • 用户仍然可以使用子系统
  • 与适配器的区别:适配器想要去“改变”接口,而装饰着是“提供”一个简单的接口

最少知识原则:减少对象之间的交互,不要让太多的类耦合在一起

8.桥接模式

从一维度变成二维度,什么意思?
在这里插入图片描述

加入我们有图形和颜色这两个维度,我们可以用这种树的形式创建4*3=12个类.
在这里插入图片描述

因此我们可以使用这种方式,把两个继承关系的类,改成组合或者聚合关系
在这里插入图片描述

  • 将抽象化和现实之间解耦
  • 抽象和现实可以独立扩展
  • 在implementor做的改变不影响客户
  • 在需要在多个平台上运行的图形和窗口系统中非常有用

9.享元模式(fly weight)

用一个实例作为许多个实例的虚拟实例.

10.重构

一些不好的行为:

  • 重复的代码
    提取方法、提取类、模板方法模式、策略模式。
    • extract: mothod当一些方法总是重复出现且应当被归为一组
    • 提取类:你让一个类做了两个类的事情,创建一个新的类,并且转移到新的类中去
    • 模版方法模式:将一些原子操作让子类去做,最后合成新的方法.
  • style
    • 注释:合适的
    • 命名:使用一种命名方式
    • dead code:删除他
  • 长方法
    • 小的方法方便理解,维护,扩展
    • 提取方法 extract method
  • 长类
    • 类的变量,事情等等太多
    • extract class, extract subclass,observer
  • 长的参数列表
    • Replace parameter with method:
      在这里插入图片描述

      让接收方去调用方法.

    • Introduce parameter object
      如果有一组参数总是在一起,请把他们变成一个对象吧!

    • Preserve whole object
      你从一个对象中得到一堆值,然后将这些对象一起传递给另一个方法,调用
      也许你应该直接传递整个对象。

  • Divergent Change (发散式变化)
    • 一个类可能会因为多种变化而需要修改,但是一个类最好只因为一种情况而需要修改
    • extract class
  • shotgun surgery (散弹式修改)
    • 一种变化可能会引起多处修改
    • Move Method:如果一个方法更多的被另一个类使用,那么我们可以把这个方法移动到新的类里
    • Move filed:某个字段被其所驻类之外的另一个类更多的用到。在目标类建立一个新字段,修改源字段,在原类中创建新的的对象,令它们改用新类的新字段。
    • 用move method和move filed把要改动的移到一个class
  • Feature Envy
    • 一个类中的方法似乎对其他类的内部结构比对自己的内部结构更感兴趣。(例如羡慕数据)
    • Extract method, Move method, Move field (先提取函数再搬运函数:如果函数中只有一部分受此之苦)
  • 数据泥团(Data Clumps)
    • 一堆在一起的数据,总是在一起的参数.
    • extract class, Preserve whole object, Introduce parameter object
  • primitive obsession(基本类型偏执)
    • Replace data value(s) with object:你有一个数据项需要额外的数据或行为。

    • Replace type code with class
      在这里插入图片描述

    • Replace type code with state/strategy

  • Switch statements
    在这里插入图片描述
    • Extract method, Move method, Replace type code with subclasses, Replace type code with state/strategy,
    • Replace conditional with polymorphism:使用多态从而避免switch
  • 冗余类 lazy class
    • Collapse hierarchy

    • Inline class

  • Speculative Generality(夸夸其谈未来性)
    • Collapse hierarchy, Rename method, Remove parameter, Inline class
  • 令人迷惑的暂时字段 temporary field
    • 某个实例变量仅为某种特定情况而设
      解决方案:使用extract class为其创造一个家,把所有和这个变量相关的代码都放进这个家。
      解决方案:再变量不合法的情况下,使用introduce null object 创建一个null 对象,从而避免写出条件式代码
  • Message Chains(过度耦合的消息链,或者说过长的消息连)
    • Hide delegate, Extract method, Move method
    • Hide delegate:用一个函数包装罢了
  • Middleman
    • Remove middle man (duh!), Inline method, Replace delegation with inheritance

    • Remove middle man在这里插入图片描述

      在Hide Delegate(隐藏“委托关系”)的“动机”一节中讲到“封装受托对象”的好处。但是这层封装也是要付出代价的,他的代价就是:每当客户要是用受托类的新特性时,你就必须在服务端添加一个简单委托函数。随着受托类得特性(功能)越来越多,这一过程会让你痛苦不已。服务类完全变成一个“中间人”,此时你就应该让客户直接调用受托类。
      很难说什么程度的隐藏才是合适的。还好,有了Hide Delegate和Remove Middle Man,你大可不必操心这个问题,因为你可以在系统运行过程中不断进行调整。随着系统的变化,“合适的隐藏程度”这个尺度也相应改变。6个月月前恰如其分的封装,现今可能就显得笨拙。重构的意义就在于:你永远不必说对不起—只要把出问题的地方修不好就行了。

  • Inappropriate Intimacy(狎昵关系)
    就像古代恋人一样,过份狎昵的classes必须拆散。你可以采用Move Method和Move Field帮它们划清界线,从而减少狎昵行径。你也可以看看是否运用Change Bidirectional Association to Unidirectional[将双向关联改为单向]让其中一个class对另一个斩断情丝。如果两个classes实在情投意合,可以运用Extract Class把两者共同点提炼到一个安全地点,让它们坦荡地使用这个新class。或者也可以尝试运用Hide Delegate让另一个class来为它们传递相思情。
    继承往往造成过度亲密,因为subclass对superclass的了解总是超过superclass的主观愿望。如果你觉得该让这个孩子独自生活了,请运用Replace Inheritance with Delegation让它离开继承体系。
    • Encapsulate collection封装集合就是把集合进行封装,只提供调用者所需要的功能行借口,保证集合的安全性。
      详解:在大多的时候,我们没有必要把所有的操作暴露给调用者,只需要把调用者需要的相关操作暴露给他,这种情况中下我们就要对其进行封装,只把调用者需要的部分暴露出来。
  • Alternative Classes with Different Interfaces(异曲同工的类)
    • Extract superclass, Unify interfaces with adapter(用户和两个类打交道,两个类提供类似的功能,但是借口不一样,使用Adapter提供统一的接口 )
  • Refused Bequest(被拒绝的遗赠)
    • 按传统说法,这就意味继承体系设计错误。你需要为这个subclass新建一个兄弟,再运用Push Down Method和Push Down Field把所有用不到的方法下推给那兄弟。这样一来superclass就只持有所有subclasses共享的东西。常常你会听到这样的建议:所有 superclasses都应该是抽象的。
    • Replace Inheritance with Delegation Example在这里插入图片描述

10.小彩蛋

第一个女程序员:Ada Lovelace
C++发明者:Bjane Stroustrup

11.模式分类

1.创建型模式
简单工厂模式(Simple Factory)
工厂方法模式(Factory Method)
抽象工厂模式(Abstract Factory)
单例模式(Singleton)

2.结构型模式
外观模式/门面模式(Facade门面模式)
适配器模式(Adapter)
桥梁模式/桥接模式(Bridge)
享元模式(Flyweight)

3.行为型模式
策略模式
观察者模式
命令模式

12.OO原则

封装变化
多用组合(interface),少用继承
针对接口编程
为交互对象之间松耦合而努力
对扩展开放,对修改关闭
依赖抽象,不要依赖具体
只和朋友交谈

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值