zoukankan      html  css  js  c++  java
  • 设计模式 复习记录

    好的面向对象设计具有复用性,灵活性,可维护性;
    设计模式告诉你如何设计一个高OO质量的系统;
    设计模式是经过验证的面向对象经验;为反复出现的特定问题提供通用的解决方案;
    与代码重用不同,使用设计模式可以获得经验重用;
    每个模式描述了一个反复出现的面向对象问题,以及他的通用的解决方案;

    设计模式四个组成:名称,问题,解决方案,影响;

    Inheritance 继承
    Change 变化;导致变化的因素很多,代码改变快

    设计原则:封装变化

    识别应用中变化的部分,把他与不变的部分分隔开;
    封装变化的部分,修改时就不会影响不变的部分

    设计原则:面向接口而不是实现;

    Polymorphism 多态
    就是面向超类,对象使用父类而不是具体子类定义,这样对象定义时不需要知道具体类型;
    这个超类 可以是class 可以是interface
    优点:得到复用的好处,又没有继承带来的负担

    设计原则:组合比继承更好;has-a比is-a更好;

    更好的灵活性;

    策略模式; strategy ,policy

    定义一个算法家族,封装每个,让每个是可更换的;让算法的变化独立于他的使用者;
    应用:
    1.许多相关类只有他们的行为不同;
    2. 需要一个算法的不同变体;
    3. 不让算法数据暴露给使用者;
    4. 类定义了很多行为,通过条件进行选择,可以将行为移动到策略类中;

    影响:替代子类化的方法;策略模式消除了选择语句;用户必须了解各种策略的不同去选择合适的;增加对象数量;

    观察者模式:observer,dependents,publish-subscribe

    定义了对象间一对多的依赖,当一个对象(发布者)改变状态,所有依赖者被通知并自动更新;
    一对多关系:发布者唯一拥有state,observer依赖发布者更新自己when状态变化时;
    更加清晰,相比于多个对象拥有相同的数据; subject和observer之间松耦合;

    Subject维护observer的数组; observer维护subject的引用,解除关系时使用;
    Java内置Observable类(subject)和Observer接口;【observable类限制了子类的继承,理论上可以使用组合,但是setChanged()方法是protected,所以不行;可以自己实现】
    应用:GUI,界面和数据进行交互;
    实现:当subject很多observer很少,可使用hashMap进行关系映射,减少subject维护的数据量;
    一个observer对应多个subject,将subject作为arg传入update(), 方便observer知道执行那个subject;
    调用update():subject改变状态通知后,调用update,不用client关心,但是可能导致连续多次update(),效率低;
    Client在特定时间调用notify,可在一系列op后调用,缺点是client可能忘记;
    Push:subject推送全数据到observer,不管他要不要;pull:sub进行通知,由obs自己用引用去取数据;
    Pull让sub忽略obs,但强调obs要知道什么数据变了;push让sub更低重用,coz对ops的假设不一定对;
    显示指定感兴趣修改当obs加入sub时,当某事发生时,sub通知特定的obs,(通过维护不同数组);
    变体:changeManager, 维护obs和sub的复杂映射关系,定义update策略,(eg,一个op导致多个sub变化,manager在全部sub都改变后在通知obs,防止对obs的重复通知);

    影响:独立的改变sub和obs,不会影响对方;
    Sub只知道obs实现了接口,不知道具体实现,耦合低;双方可以属于系统的不同层次;
    因为Obs不知道各自的存在,所以对sub改变的代价很盲目,可能导致obs的级联update;没有很好维护的依赖可能导致错误的update,很难追踪;

    设计原则:尽量使交互的对象之间松耦合;

    更加接纳变更的灵活系统;

    装饰者模式:Decorator,wrapper

    Decorator和decorated拥有同一个超类;
    装饰着修改了comp的行为,通过添加新的功能,在调用comp的方法的之前和/或之后;
    动态地向对象附加了额外的职责,为扩展功能提供了灵活的方法 替代子类化;

    应用:Java IO相关的类,stream
    动机

    1. 添加职责到单独的对象,而不是整个类,比如GUI构件根据不同需求的组合;
    2. 保持comp类的轻量级;最顶层的超类只是定义接口,不要存储数据;否则太重让他不能大量使用,且子类可能拥有不需要的功能;
    3. 表面vs内部; 装饰者模式是改变行为的皮肤,策略模式改变行为的内部;
      当comp类本质上很重时,使用策略,装饰者成本很高;策略模式中comp将行为转化为单独的策略对象;

    开闭原则:类应该对扩展开放,对修改关闭;

    (不需要在所有地方使用,是浪费的,导致过度复杂)
    组合和委托 通常可以用于在运行时添加新的行为;

    工厂方法模式:factory method,

    定义一个创建对象的接口,让子类确定实例化哪一个类;

    依赖倒置原则:依赖抽象,不要依赖具体的类;

    高层类必要依赖底层类,双方都依赖于抽象。
    “倒置”是指top-to-down的依赖关系颠倒了自己,top和down都依赖于抽象。
    指导方针:

    1. 任何变量不应有具体类的引用,使用工厂方法得到对象;
    2. 任何类不应派生自具体类,使用接口或抽象类;
    3. 任何方法不应覆盖基类方法;说明基类不是真正抽象; (指导方针只要争取,不用作为遵守的原则)

    抽象工厂方法模式:abstract factory method,

    提供一个生产一系列关联产品族的接口(抽象工厂);
    常见相关的一系列产品,而不与具体类耦合;

    命令模式:command,action,transaction

    将“请求”封装成对象,以使用不同的请求、队列、日志来参数化其他对象,支持撤销操作。
    命令对象包装动作和接收者,只暴露execute()方法;将发出请求的对象和执行请求的对象解耦,通过命令沟通;

    撤销undo()方法:内容和execute()方法相反;当调用一个命令execute(),就将invoker的undoCommand置为该命令;
    动机:1.解耦请求的操作和请求的执行者;
    应用:
    1.日志,store()和load()方法,进行日志记录,系统崩溃时重新执行;
    2. Java 的GUI 委派事件模型, listener的匿名类实现不同业务;
    3. 命令模式 是回调函数的对象替代;
    4. 命令对象的生存期可以独立于原始请求,

    单例模式:singleton

    公共静态get方法,私有构造方法,

    1. 提前加载:使用静态field,在定义时进行new;
    2. 懒加载: 异步安全:
    		Public static synchronized Singleton getInstance(){
    			If(instance == null) instance = new Singleton(); 
    			Return instance;
    		}
    

    双重检查:

    Public static Singleton getInstance(){
    	If(instance == null) { 
    		synchronized (Singleton.class){
    			if(instance == null) instance = new Singleton(); 
    		}
    	}
    	Return instance;
    }    
    

    适配器模式:adapter,wrapper

    将一个类的接口转换成客户希望的另一个接口。适配器模式让那些接口不兼容的类可以一起工作。
    Target:定义客户所需的接口,可以是一个抽象类或接口,也可以是具体类。
    Adapter:它可以调用另一个接口,作为一个转换器,对Adaptee和Target进行适配。
    Adaptee:适配者即被适配的角色,它定义了一个已经存在的接口,这个接口需要适配,适配者类包好了客户希望的业务方法。
    执行逻辑:Client需要调用adaptee的功能,但是他只能以target的方法来调用;adapter实现target接口,继承adaptee或者得到一个adaptee成员,在request()方法内部调用adaptee的方法; Client调用实现了target接口的adapter就行,不用去使用adaptee;

    adapter可以继承adaptee类, 也可以将adapteee作为field保存在adapter类里面;

    外观模式 façade:

    提供一个标准接口,包装子系统一系列操作,将client从子系统一系列组件中解耦出来;

    最少知识原则:仅仅和你最紧密的类交谈;

    对象的方法内只能调用:
    对象本身的方法;作为参数传入的对象的方法;方法内创建的对象的方法;对象的field的方法;
    过度使用会让系统的复杂性增高;

    适配器模式包装一个对象 去改变他的接口;
    装饰模式 包装一个对象 来添加新的行为职责;
    外观模式 包装一系列对象来简化功能;

    模板方法模式:template method

    在方法中定义算法的框架,将定义推迟到子类。允许子类在不改变算法框架的情况下,重定义算法的某些步骤。

    可以在templateMethod()方法中添加hook()方法,目的是让子类可以选择是否添加步骤;

    迭代器模式:iterator

    封装迭代,不让client了解到聚合对象的具体实现;

    单一职责原则:一个类只应该因为一个原因而变化。

    组合模式:Composite

    让client能相同地处理单一对象和组合对象;
    以树的形式构建对象的结构,树包含对象的组合和作为节点的单个对象;
    组合模式让我们可以对复合对象和单个对象应用相同的操作。

    状态模式:state

    当对象的内部状态变化时,允许他改变自己的行为;

    策略模式通常使用行为或算法配置上下文类。
    状态模式允许上下文在上下文状态更改时更改其行为。

    代理模式:proxy

    代理模式为另一个对象提供代理项或占位符以控制对它的访问。

    Realsubject是做真正工作的对象,proxy控制对他的访问;
    Proxy保存realsubject的引用,管理对realsubject的调用,proxy进行realsubject的创建工作;
    Subject接口,由realsubject和proxy共同实现,client可以把proxy当成realsubject一样使用;

    【参考资料】
    Freeman E, Freeman E, Sierra K, et al. Head First 设计模式[J]. 中文版中文版, 2007: 20071-36.

  • 相关阅读:
    java8关于list的操作
    jdk8的.toMap()
    Mybatis中报错org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)问题解决
    springboot集成bootstrap遇到的问题
    java文件下载
    idea中mybatis自动生成代码方式
    文件读写操作inputStream转为byte[] , 将InputStream写入本地文件
    Polar transformer networks
    Fine-Grained Person Re-identification
    Person Re-identification by Contour Sketch under Moderate Clothing Change
  • 原文地址:https://www.cnblogs.com/billxxx/p/12128928.html
Copyright © 2011-2022 走看看