精华内容
下载资源
问答
  • 问题聚焦: 行为模式,将你的注意力从控制流转移到对象间的联系通信方式上来。 本节所介绍的职责链,是典型的松耦合设计模式。 职责链模式可以相应多个请求接受者,选择其中最合适的处理者。
    问题聚焦:
    
        行为模式,将你的注意力从控制流转移到对象间的联系通信方式上来。
        本节所介绍的职责链,是典型的松耦合设计模式。
        职责链模式可以相应多个请求接受者,选择其中最合适的处理者。



    行为模式:
    定义:算法和对象间职责的分配,不仅描述对象或类的模式,还描述它们之间的通信模式。
    使用继承机制:使用继承机制在类间分派行为。如Tempalte Method和Interpreter。
    使用对象复合:一些行为对象模式描述了一组对等的对象怎样相互协作以完成其中任一个对象都无法单独完成的任务。其要注意的问题是如何低耦合又保持相互的了解。如Mediator模式提供的松耦合所需的间接性。
    职责链(Chain of Responsibility)通过一条候选对象链式向一个对象发送请求。
    观察者模式(Oberserver)定义并保持对象间的依赖关系。
    其他的行为对象模式常将行为封装在一个对象中并将请求指派给它。

    职责链(Chain Of Responsibility)
    意图:
    使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。
    将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

    动机:
    依然以一个实际的例子说明该模式的设计出发点。
    Demo:
        考虑一个图形用户界面中的帮助机制设计
        需求:用户在界面的任一部分上点击就可以得到帮助信息,所提供的帮助依赖于点击的是界面的哪一部分以及其上下文。
                   如果对那一部分界面没有特定的帮助信息,那么帮助系统应该显示一个关于当前上下文的较一般的帮助信息。比如,整个对话框的帮助信息。
        思路:从特殊到普遍的顺序组织帮助信息,有一个对象专门负责选择帮助请求。
        挑战:提交帮助请求的对象并不明确知道谁是最终提供帮助的对象。我们要做的是将提交帮助请求的对象与可能提供帮助信息的对象解耦和。
                  给多个对象处理一个请求的机会,挑选最适合的处理者,从而解耦发送者和接受者。该请求将按对象链传递,知道一个合适的请求接受者对它作出反应。
        如下图所示:
            
            在PrintButton和OKButton接收到的请求并不直接处理,而是沿转发链向下转发至PrintDialog,一直到Application,Application处理它或忽略它。
            效果就是,提交请求的客户不直接引用最终相应它的对象。
        实现:要沿链转发请求,并保证接收者为隐式的(implicit),每个链上的对象都有一致的处理请求和访问链上后继者的接口。
        设计:HelpHandler类,作为所有候选对象类的父类,用HelpHandler定义的接口处理帮助请求,或者下发请求。
                   HandleHelp操作缺省的是将请求转发给后继,子类可重定义这一操作以在适当的情况下提供帮助;否则它们可使用缺省实现转发该请求。
                


    适用性:
    以下情况使用Responsibility链:
    • 有多个的对象可以处理一个请求,哪个对象处理该请求,在运行时刻自动确定。
    • 你想在不明确指定接受者的情况下,向多个对象中的一个,提交一个请求。
    • 可处理一个请求的对象集合应被动态指定。 
    结构:

    一个典型的对象结构可能如下图所示:

    参与者:
    • Handler(HelpHandler):
      •     定义一个处理请求的接口
      •     实现后继
    • Concretehandler(PrintButton):
      •     处理它负责的请求
      •     可访问它的后继者
      •     如果可处理该请求,就处理;否则将该请求转发给它的后继者
    • Client:向链上的具体处理者对象提交请求
    协作:
     当客户提交一个请求时,请求沿链传递直至有一个ConcreteHandler对象负责处理它。

    效果:
    优点和缺点
    • 降低耦合度:请求提交者无需知道哪一个对象处理请求;请求接受者不需要知道链的存在,它只需要知道它的后继是谁。
    • 增强了给对象指派职责的灵活度
    • 不保证被接受:当请求到达链尾仍没有被处理时,就得不到处理。



    实现:
    下面是在职责链模式中要考虑的实现问题:
    • 实现后继者链(接受请求者组成的处理请求链):
      •     定义新的链接
      •     使用已有的链接:在组合模式(Composite)中详细地讨论了适合作后继者链的结构
    • 连接后继者:如果没有一个可使用的引用定义一个链,那么Handler不仅定义该请求的接口,通常也维护后继链接。这时,Concretehandler子类对该请求不感兴趣时,进行无条件转发。
    • 表示请求:三种方式表示请求
      • 简单地,硬编码操作调用,缺点,只能转发定义的固定的一组请求
      • 使用处理函数,接受一个请求码。
      • 使用独立的请求对象请求参数。   
    代码示例:
    下面以前面所述的在线帮助系统,来演示职责链是如何处理请求的。
    类设定:
    HelpHandler类定义了处理帮助请求的接口。
    职责:维护一个帮助主题;保持对帮助处理对象链中的后继者的引用
    关键操作:HanldeHelp,可被子类重定义;HasHelp辅助操作,用于检查是否有一个相关的帮助主题。
    typedef int Topic;
    const Topic NO_HELP_TOPIC = -1;
    
    class HelpHandler {
    public:
        HelpHanlder(HelpHandler* = 0, Topic = NO_HELP_TOPIC);
        virtual bool HasHelp();
        virtual void SetHandler(HelpHandler*, Topic);
        virtual void HandleHelp();
    private:
        HelpHandler* _successor;
        Topic _topic;
    };
    
    HelpHandler::HelpHandler(HelpHandler* h, Topic t)
        : _successor(h), _topic(t) {}
    
    HelpHandler::HandlerHelp () {
        if (_successor != 0) {
            _successor->HandleHelp();
        }
    }
    Widget抽象类:所有窗口组件的父类
    class Widget : public HelpHandler {
    protected:
        Widget(Widget* parent, Topic t = NO_HELP_TOPIC);
    private:
        Widget* _parent;
    };
    
    Widget::Widget (Widget* w, Topic t) : HelpHandler(w, t) {
        _parent = w;
    }
    按钮是链上的第一个处理者
    class Button : public Widget {
    public:
        Button(Widget* d, Topic t = NO_HELP_TOPIC);
        virtual void HandleHelp();
    };
    
    Button::Button (Widget* h , Topic t) : Widget(h, t) { }
    
    void Button::HandleHelp () {
        if (HasHelp()) {
            // offer help on the request    
        }
        else {
            HelpHandler::HandleHelp();
        }
    }
    Dialog实现了一个类似的策略。其后继者不仅可以是一个窗口组件,还可以是任意的帮助请求处理对象。
    class Dialog : public Widget {
    public:
        Dialog(HelpHandler* h, Topic t = NO_HELP_TOPIC);
        virtual void HandleHelp();
    };
    
    Dialog::Dialog(HelpHandler* h, Topic t) : Widget(0) {
        SetHandler(h, t);
    }
    
    void Dialog::HandleHelp() {
        if (HasHelp()) {
            // offer help    
        }
        else {
                HelpHandler::HandleHelp();
        }
    }
    在链的末端是Application的一个实例。
    class Application : public HelpHandler {
        ......
    };
    类设定完毕。
    下面的代码创建并连接这些对象。
    const Topic PRINT_TOPIC = 1;
    const Topic PAPER_ORIENTATION_TOPIC = 2;
    const Topic APPLICATION_TOPIC = 3;
    
    Application* application = new Application(APPLICATION_TOPIC);
    Dialog* dialog = new Dialog(application, PRINT_TOPIC);
    Button* button = new Button(dialog, PAPER_ORIENTATION_TOPIC);
    我们可对链上的任意对象调用HandleHelp以触发相应的帮助请求。
    button->HanleHelp();


    相关模式:
    职责链模式常与Composite模式一起使用,这种情况下,一个构件的父构件可以作为它的后继。


    参考资料:
    《设计模式:可复用面向对象软件的基础》

    展开全文
  • 几种典型的面向对象开发方法

    万次阅读 2009-05-30 01:59:00
    摘 要 自80年代后期以来,相继出现了多种面向对象开发方法,文章主要介绍了其中六种典型的面向对象开发方法,并对它们进行了比较。UML的出现意味着开发方法统一化、标准化的新发展,标志着软件自动化的进程又迈进了...

    摘 要80年代后期以来,相继出现了多种面向对象开发方法,文章主要介绍了其中六种典型的面向对象开发方法,并对它们进行了比较。UML的出现意味着开发方法统一化、标准化的新发展,标志着软件自动化的进程又迈进了一步。

    关键字 面向对象开发方法 典型 比较

     

    一、引言

    随着计算机科学的发展和应用领域的不断扩大,对计算机技术的要求越来越高。特别是当计算机硬件有了飞速发展之后,各种应用领域对软件提出了更高的要求。结构化程序设计语言和结构化分析与设计已无法满足用户需求的变化。发展软件质量,缩短软件开发周期,发展软件可靠性、可扩充性和可重用性迫使软件界人士不断研究新方法、新技术,探索新途径。

    面向对象的方法是一种分析方法、设计方法和思维方法。面向对象方法学的出发点和所追求的基本目标是使人们分析、设计与实现一个系统的方法尽可能接近人们认识一个系统的方法。也就是使描述问题的问题空间和解决问题的方法空间在结构上尽可能一致。其基本思想是:对问题空间进行自然分割,以更接近人类思维的方式建立问题域模型,以便对客观实体进行结构模拟和行为模拟,从而使设计出的软件尽可能直接地描述现实世界,构造出模块化的、可重用的、维护性好的软件,同时限制软件的复杂性和降低开发维护费用。

    面向对象程序设计方法起源于六十年代末期的语言SIMULA’67,到了七十年代末期,软件行业正受到软件危机的困扰,结构化的开发方法不能够很好地解决软件危机。面向对象语言Smalltalk的出现,进一步发展和完善了面向对象的程序设计语言,从此面向对象也和开发方法开始结合,出现了面向对象的开发方法。自80年代后期以来,相继出现了多种面向对象开发方法,现将其中几种典型的方法作一个简介和比较。

     

    二、六种典型的面向对象开发方法

    1OMT/Rumbaugh

    OMT[1]Object Modeling Technique)方法最早是由LoomisShanRumbaugh1987年提出的,曾扩展应用于关系数据库设计。Jim Rumbaugh1991年正式把OMT应用于面向对象的分析和设计。这个方法是在实体关系模型上扩展了类、继承和行为而得到的。

    OMT覆盖了分析、设计和实现三个阶段,它包括一组相互关联的概念:类(class)、对象(object)、一般化(generalization)、继承(inheritance)、链(link)、链属性(link attribute)、聚合(aggregation)、操作(operation)、事件(event)、场景(scene)、属性(attribute)、子系统(subsystem)、模块(module)等。

    OMT方法包含分析、系统设计、对象设计和实现四个步骤,它定义了三种模型,这些模型贯穿于每个步骤,在每个步骤中被不断地精化和扩充。这三种模型是:

    ·对象模型:用类和关系来刻画系统的静态结构;

    ·动态模型:用事件和对象状态来刻画系统的动态特性;

    ·功能模型:按照对象的操作来描述如何从输入给出输出结果。

    分析的目的是建立可理解的现实世界模型。系统设计确定高层次的开发策略。对象设计的目的是确定对象的细节,包括定义对象的界面、算法和操作。实现对象则在良好的面向对象编程风格的编码原则指导下进行。

     

    2 OOD/Booch

    OOD[3]Object Oriented Design)方法是Grady Booch1983年开始研究,1991年后走向成熟的一种方法。

    OOD主要包括下述概念:类(class)、对象(object)、使用(uses)、实例化(instantiates)、继承(inherits)、元类(meta class)、类范畴(class category)、消息(message)、域(field)、操作(operation)、机制(mechanism)、模块(module)、子系统(subsystem)、过程(process)等。其中,使用及实例化是类间的静态关系,而动态对象之间仅有消息传递的连接。元类是类的类。类范畴是一组类,它们在一定抽象意义上是类同的。物理的一组类用模块来表达。机制是完成一个需求任务的一组类构成的结构。

    Booch方法在面向对象的设计中主要强调多次重复和开发者的创造性。方法本身是一组启发性的过程式建议。OOD的一般过程如下:

    1)在一定抽象层次上标识类与对象;

    2)标识类与对象的语义;

    3)标识类与对象之间的关系(如继承、实例化、使用等);

    4)实现类与对象。

     

    3 RDD/Wirfs-Brock

    RDD[2]Responsibility-Driven Design)方法是Wirfs-Brock1990年提出的。这是一个按照类、责任以及合作关系对应用进行建模的方法。首先定义系统的类与对象,然后确定系统的责任并划分给类,最后确定对象类之间的合作来完成类的责任。这些设计将进一步按照类层次、子系统和协议来完善。

    RDD方法主要包含以下概念:类(class)、继承(inheritance)、责任(responsibility)、合作(collaboration)、合同(contract)、子系统(subsystem)。对每个类都有不同的责任或角色以及动作。合作是为完成责任而需要与之通信的对象集合。责任进一步精化并被分组为合同。合同又进一步按操作精化为协议。子系统是为简化设计而引入的,是一组类和低级子系统,也包含由子系统中的类及子系统支持的合同。

    RDD分为探索阶段和精化阶段:

    1)探索阶段:确定类、每个类的责任以及类间的合作;

    2)精化阶段:精化类继承层次、确定子系统、确定协议。

    RDD按照类层次图、合作图、类规范、子系统规范、合同规范等设计规范来完成实现。

     

    4 OOAD/Coad-Yourdon

    OOAD[3]Object-Oriented Analysis and Design)方法是由Peter CoadEdward Yourdon 1991年提出的。这是一种逐步进阶的面向对象建模方法。

    OOA中,分析模型用来描述系统的功能,主要包括以下概念:类(class)、对象(object)、属性(attribute)、服务(service)、消息(message)、主题(subject)、一般/特殊结构(Gen-Spec-Structure)、全局/部份结构(Whole-Part-Structure)、实例连接(instance connection)和消息连接(message connection)等。其中,主题是指一组特定的类与对象。

    OOA使用了基本的结构化原则,并把它们同面向对象的观点结合起来。

    OOA完成系统分析,包括以下五个步骤:确定类与对象、标识结构、定义主题、定义属性和定义服务。OOA本质上是一种面向对象的方法,适用于小型系统的开发。

    OOD负责系统设计,包括以下四个步骤:

    1)设计问题域(细化分析结果);

    2)设计人机交互部分(设计用户界面);

    3)设计任务管理部分(确定系统资源的分配);

    4)设计数据管理部分(确定持久对象的存储)。

     

    5 OOSE/Jacobson

    OOSE[3]Object-Oriented Software Engineering)是Ivar Jacobson1992年提出的一种使用事例驱动的面向对象开发方法。

    OOSE主要包括下列概念:类(class)、对象(object)、继承(inherits)、相识(acquaintance)、通信(communication)、激励(stimuli)、操作(operation)、属性(attribute)、参与者(actor)、使用事例(use case)、子系统(subsystem)、服务包(service package)、块(block)、对象模块(object module)。相识表示静态的关联关系,包括聚合关系。激励是通信传送的消息。参与者是与系统交互的事物,它表示所有与系统有信息交换的系统之外的事务,因此不关心它的细节。参与者与用户不同,参与者是用户所充当的角色。参与者的一个实例对系统做一组不同的操作。当用户使用系统时,会执行一个行为相关的事物系列,这个系列是在与系统的会话中完成的,这个特殊的系列称为使用事例,每个使用事例都是使用系统的一条途径。使用事例的一个执行过程可以看作是使用事例的实例。当用户发出一个激励之后,使用事例的实例开始执行,并按照使用事例开始事物。事务包括许多动作,事务在收到用户结束激励后被终止。在这个意义上,使用事例可以被看作是对象类,而使用事例的实例可以被看作是对象。

    OOSE开发过程中有以下五种模型,这些模型是自然过渡和紧密耦合的:

    ·需求模型包括由领域对象模型和界面描述支持的参与者和使用事例。对象模型是系统的概念化的、容易理解的描述。界面描述刻画了系统界面的细节。需求模型从用户的观点上完整地刻画了系统的功能需求,因此按这个模型与最终用户交流比较容易。

    ·分析模型是在需求模型的基础上建立的。主要目的是要建立在系统生命期中可维护、有逻辑性、健壮的结构。模型中有三种对象。界面对象刻画系统界面。实体对象刻画系统要长期管理的信息和信息上的行为。实体对象生存在一个特别的使用事例中。第三种是按特定的使用事例作面向事务的建模的对象。这三种对象使得需求的改变总是局限于其中一种。

    ·设计模型进一步精化分析模型并考虑了当前的实现环境。块描述了实现的意图。分析模型通常要根据实现作相应的变化。但分析模型中基本结构要尽可能保留。在设计模型中,块进一步用使用事例模型来阐述界面和块间的通信。

    ·实现模型主要包括实现块的代码。OOSE并不要求用面向对象语言来完成实现。

    ·测试模型包括不同程度的保证。这种保证从低层的单元测试延伸到高层的系统测试。

     

    6 VMT/IBM

    VMT[1]Visual Modeling Technique)方法是IBM公司于1996年公布的。VMT方法结合了OMTOOSERDD等方法的优点,并且结合了可视化编程和原型技术。VMT方法选择OMT方法作为整个方法的框架,并且在表示上也采用了OMT方法的表示。VMT方法用RDD方法中的CRCClass-Responsibility-Collaboration)卡片来定义各个对象的责任(操作)以及对象间的合作(关系)。此外,VMT方法引入了OOSE方法中的使用事例概念,用以描述用户与系统之间的相互作用,确定系统为用户提供的服务,从而得到准确的需求模型。

    VMT方法的开发过程分为三个阶段:分析、设计和实现。分析阶段的主要任务是建立分析模型。设计阶段包括系统设计、对象设计和永久性对象设计。实现阶段就是用某一种环境来实现系统。

     

    7、六种方法的比较

    ·OMT方法覆盖了应用开发的全过程,是一种比较成熟的方法,用几种不同的观念来适应不同的建模场合,它在许多重要观念上受到关系数据库设计的影响,适合于数据密集型的信息系统的开发,是一种比较完善和有效的分析与设计方法。

    ·Booch方法并不是一个开发过程,只是在开发面向对象系统时应遵循的一些技术和 原则。Booch方法是从外部开始,逐步求精每个类直到系统被实现。因此,它是一种分治法,支持循环开发,它的缺点在于不能有效地找出每个对象和类的操作。

    ·RDD是一种用非形式的技术和指导原则开发合适的设计方案的设计技术。它用交互 填写CRC卡片的方法完成设计,对大型系统设计不太适用。RDD采用传统的方法确定对象类,有一定的局限性。另外,均匀地把行为分配给类也十分困难。

    ·OOAD方法中,OOA把系统横向划分为五个层次,OOD把系统纵向划分为四个部分,从而形成一个清晰的系统模型。OOAD适用于小型系统的开发。

    ·OOSE能够较好地描述系统的需求,是一种实用的面向对象的系统开发方法,适合于商务处理方面的应用开发。

    ·VMT基于现有面向对象方法中的成熟技术,采用这些方法中最好的思想、特色、观点以及技术,并把它们融合成一个完整的开发过程。因此VMT是一种扬长避短的方法,它提供了一种实用的能够处理复杂问题的建模方法和技术。

     

    三、建模语言UML

    建模语言UML[4]最初仅仅是OMT方法、Booch方法的统一。199510月,Grady BoochJim Rumbaugh联合推出了Unified Method 0.8版本。这个方法力图实现OMT方法和Booch方法的统一。同年秋天,Ivar Jacobson加入了BoochRumbaugh所在的Rational软件公司,于是OOSE方法也加入了统一的过程中。199791日产生了UML 1.1,并被提交到了OMGObject Management Group),同年11月被OMG采纳。

    按照UML文件的说法:UML是一种用于软件系统制品制约的、可视化的构造及建档语言,也可用于业务建模以及其它非软件系统。

    从系统模型这一级别上看,UML表示法由9种图构成,它们是:静态结构图(Static Structure Diagram),其中包括类图(Class Diagram)和对象图(Object Diagram);使用事例图(Use Case Diagram);顺序图(Sequence Diagram);协作图(Collaboration);状态图(Statechart Diagram);活动图(Activity Diagram);实现图(Implementation Diagram),其中包括成分图(Component Diagram)和展开图(Deployment Diagram)。UML的通用表示还有:串(String)、名字(Name)、标签(Label)、关键字(Keyword)、表达式(Expression)、注释(Note)等。

    UML作为一种建模语言,具有以下特点:

    ·UML结合了Booch方法、OMT方法和OOSE方法的概念,是一个单一的通用的建模语言;

    ·UML的建模能力比其他面向对象方法更强,不仅适合于一般系统的开发,更擅长于并行、分布式系统的建模;

    ·UML是一种标准的建模语言,而不是一个标准的开发过程,它完全独立于开发过程。

     

    四、结束语

    要想实现软件生产自动化,实现开发方法的统一化、标准化是基本的一条。实现面向对象开发方法的标准化以后,就可以避免不同方法的差异,提高软件重用效率。此外,统一面向对象开发方法,也就是综合每个面向对象方法的优点,最大限度地发挥各种方法的长处。

    UML是一种表达能力丰富的建模语言,而不是一种方法,因此,目前它还不能取代现有的各种面向对象的分析与设计方法。但是,随着UML工作的进一步展开,必将有助于实现软件自动化。

    展开全文
  • 几种典型的面向对象开发方法总结

    千次阅读 2012-11-17 09:45:15
    重要的概念模型是类和对象、类和对象的特征、类和对象之间的关系。使用的图形文档包括六种: 类图、对象图、状态转换图、交互图、模块图和进程图。 Booch方法的开发过程: (1) 在给定的抽象层次上识别类和对象...

    1.      Booch方法

    Booch方法所采用的对象模型要素是:封装、模块化、层次类型、并发。重要的概念模型是类和对象、类和对象的特征、类和对象之间的关系。使用的图形文档包括六种: 类图、对象图、状态转换图、交互图、模块图和进程图。

    Booch方法的开发过程:

    (1)      在给定的抽象层次上识别类和对象。

    (2)      识别这些对象和类的语义。

    (3)      识别这些类和对象之间的关系。

    (4)      实现类和对象。

    2.      Coad 方法

    Coad方法主要由面向对象分析和面向对象设计构成。他强调的是OOA(面向对象分析)和OOD(面向对象设计)采用完全一致的概念和表示法,使分析和设计之间不需要表示法的转换。

    Coad方法主要包括两个大过程:OOA和OOD

    (1).      OOA(面向对象分析)

    面向对象分析中跟Booch方法一样首先要在给定的抽象层次上发现类和对象。第二步在类和对象的基础上识别类的层次结构、识别整体与部分之间的关系结构。第三步就是主题划分,通过主题划分来将整个大系统分解为若干主题的子系统。第四步定义属性,即定义对象的数据或状态信息。第五步定义服务,所谓服务就是对象的具体行为。

    (2).      OOD

    OOD的设计模型在面向对象的分析的5个层次基础上由4个部件组成:问题域部件、人机交互部件、任务管理部件、数据管理部件

    问题域部件设计即了解开发系统的应用领域,即在客观世界中由该系统处理的业务范围,在此基础之上对面向对象分析的5各层次不断完善。

    人机交互部件即对人机交互界面的设计。

    任务管理部件设计即明确划分任务的类型,并把任务分配到硬件或软件上去。

    数据管理部件即各种数据存储的设计,通常有文件系统和数据库管理系统两类存储模式。

    3. OMT方法

       OMT方法提供了3种模型来描述系统:对象模型、动态模型和功能模型

      对象模型描述对象的静态结构和他们之间的关系,静态模型的建立提供了系统静态功能的描述。

      动态模型描述系统随时间变化的变化及行为。

      功能模型主要描述系统内部数据值的变换。

             OMT方法的四个阶段:                                  

    (1)      分析

    分析阶段建立问题域,分析对象模型、动态模型、功能模型的结构组成。

    (2)      系统设计

    跟Coad设计方法的主题划分相似将系统分解为若干子系统。

    (3)      对象设计

    基于分析的3中模型结构完成对象设计、建立动态模型、建立功能模型。

    (4)      实现

    将设计转化为编程,实现系统。

             

    展开全文
  • Go基础编程:面向对象—接口

    千次阅读 2017-12-29 14:55:46
    接口类型是一种抽象的类型,它不会暴露出它所代表的对象的内部值的结构和这个对象支持的基础操作的集合,它们只会展示出它们自己的方法。因此接口类型不能将其实例化。 Go通过接口实现了鸭子类型(duck-typing):...

    1 概述

    在Go语言中,接口(interface)是一个自定义类型,接口类型具体描述了一系列方法的集合。

    接口类型是一种抽象的类型,它不会暴露出它所代表的对象的内部值的结构和这个对象支持的基础操作的集合,它们只会展示出它们自己的方法。因此接口类型不能将其实例化

    Go通过接口实现了鸭子类型(duck-typing):“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子”。我们并不关心对象是什么类型,到底是不是鸭子,只关心行为。

    2 接口的使用

    2.1 接口定义

    type Humaner interface {
        SayHi()
    }
    • 接⼝命名习惯以 er 结尾
    • 接口只有方法声明,没有实现,没有数据字段
    • 接口可以匿名嵌入其它接口,或嵌入到结构中

    2.2 接口实现

    接口是用来定义行为的类型。这些被定义的行为不由接口直接实现,而是由用户定义的类型实现,一个实现了这些方法的具体类型是这个接口类型的实例。

    如果用户定义的类型实现了某个接口类型声明的一组方法,那么这个用户定义的类型的值就可以赋给这个接口类型的值。这个赋值会把用户定义的类型的值存入接口类型的值。

    type Humaner interface {
        SayHi()
    }
    
    type Student struct { //学生
        name  string
        score float64
    }
    
    //Student实现SayHi()方法
    func (s *Student) SayHi() {
        fmt.Printf("Student[%s, %f] say hi!!\n", s.name, s.score)
    }
    
    type Teacher struct { //老师
        name  string
        group string
    }
    
    //Teacher实现SayHi()方法
    func (t *Teacher) SayHi() {
        fmt.Printf("Teacher[%s, %s] say hi!!\n", t.name, t.group)
    }
    
    type MyStr string
    
    //MyStr实现SayHi()方法
    func (str MyStr) SayHi() {
        fmt.Printf("MyStr[%s] say hi!!\n", str)
    }
    
    //普通函数,参数为Humaner类型的变量i
    func WhoSayHi(i Humaner) {
        i.SayHi()
    }
    
    func main() {
        s := &Student{"mike", 88.88}
        t := &Teacher{"yoyo", "Go语言"}
        var tmp MyStr = "测试"
    
        s.SayHi()   //Student[mike, 88.880000] say hi!!
        t.SayHi()   //Teacher[yoyo, Go语言] say hi!!
        tmp.SayHi() //MyStr[测试] say hi!!
    
        //多态,调用同一接口,不同表现
        WhoSayHi(s)   //Student[mike, 88.880000] say hi!!
        WhoSayHi(t)   //Teacher[yoyo, Go语言] say hi!!
        WhoSayHi(tmp) //MyStr[测试] say hi!!
    
        x := make([]Humaner, 3)
        //这三个都是不同类型的元素,但是他们实现了interface同一个接口
        x[0], x[1], x[2] = s, t, tmp
        for _, value := range x {
            value.SayHi()
        }
        /*
            Student[mike, 88.880000] say hi!!
            Teacher[yoyo, Go语言] say hi!!
            MyStr[测试] say hi!!
        */
    }

    通过上面的代码,你会发现接口就是一组抽象方法的集合,它必须由其他非接口类型实现,而不能自我实现。

    3 接口组合

    3.1 接口嵌入

    如果一个interface1作为interface2的一个嵌入字段,那么interface2隐式的包含了interface1里面的方法。

    type Humaner interface {
        SayHi()
    }
    
    type Personer interface {
        Humaner //这里想写了SayHi()一样
        Sing(lyrics string)
    }
    
    type Student struct { //学生
        name  string
        score float64
    }
    
    //Student实现SayHi()方法
    func (s *Student) SayHi() {
        fmt.Printf("Student[%s, %f] say hi!!\n", s.name, s.score)
    }
    
    //Student实现Sing()方法
    func (s *Student) Sing(lyrics string) {
        fmt.Printf("Student sing[%s]!!\n", lyrics)
    }
    
    func main() {
        s := &Student{"mike", 88.88}
    
        var i2 Personer
        i2 = s
        i2.SayHi()     //Student[mike, 88.880000] say hi!!
        i2.Sing("学生哥") //Student sing[学生哥]!!
    }

    3.2 接口转换

    超集接⼝对象可转换为⼦集接⼝,反之出错:

    type Humaner interface {
        SayHi()
    }
    
    type Personer interface {
        Humaner //这里像写了SayHi()一样
        Sing(lyrics string)
    }
    
    type Student struct { //学生
        name  string
        score float64
    }
    
    //Student实现SayHi()方法
    func (s *Student) SayHi() {
        fmt.Printf("Student[%s, %f] say hi!!\n", s.name, s.score)
    }
    
    //Student实现Sing()方法
    func (s *Student) Sing(lyrics string) {
        fmt.Printf("Student sing[%s]!!\n", lyrics)
    }
    
    func main() {
        //var i1 Humaner = &Student{"mike", 88.88}
        //var i2 Personer = i1 //err
    
        //Personer为超集,Humaner为子集
        var i1 Personer = &Student{"mike", 88.88}
        var i2 Humaner = i1
        i2.SayHi() //Student[mike, 88.880000] say hi!!
    }

    4 空接口

    空接口(interface{})不包含任何的方法,正因为如此,所有的类型都实现了空接口,因此空接口可以存储任意类型的数值。它有点类似于C语言的void *类型。

        var v1 interface{} = 1     // 将int类型赋值给interface{}
        var v2 interface{} = "abc" // 将string类型赋值给interface{}
        var v3 interface{} = &v2   // 将*interface{}类型赋值给interface{}
        var v4 interface{} = struct{ X int }{1}
        var v5 interface{} = &struct{ X int }{1}

    当函数可以接受任意的对象实例时,我们会将其声明为interface{},最典型的例子是标准库fmt中PrintXXX系列的函数,例如:

        func Printf(fmt string, args ...interface{})
        func Println(args ...interface{})

    5 类型查询

    我们知道interface的变量里面可以存储任意类型的数值(该类型实现了interface)。那么我们怎么反向知道这个变量里面实际保存了的是哪个类型的对象呢?目前常用的有两种方法:

    • comma-ok断言
    • switch测试

    5.1 comma-ok断言

    Go语言里面有一个语法,可以直接判断是否是该类型的变量: value, ok = element.(T),这里value就是变量的值,ok是一个bool类型,element是interface变量,T是断言的类型。

    如果element里面确实存储了T类型的数值,那么ok返回true,否则返回false。

    示例代码:

    type Element interface{}
    
    type Person struct {
        name string
        age  int
    }
    
    func main() {
        list := make([]Element, 3)
        list[0] = 1       // an int
        list[1] = "Hello" // a string
        list[2] = Person{"mike", 18}
    
        for index, element := range list {
            if value, ok := element.(int); ok {
                fmt.Printf("list[%d] is an int and its value is %d\n", index, value)
            } else if value, ok := element.(string); ok {
                fmt.Printf("list[%d] is a string and its value is %s\n", index, value)
            } else if value, ok := element.(Person); ok {
                fmt.Printf("list[%d] is a Person and its value is [%s, %d]\n", index, value.name, value.age)
            } else {
                fmt.Printf("list[%d] is of a different type\n", index)
            }
        }
    
        /*  打印结果:
        list[0] is an int and its value is 1
        list[1] is a string and its value is Hello
        list[2] is a Person and its value is [mike, 18]
        */
    }

    5.2 switch测试

    type Element interface{}
    
    type Person struct {
        name string
        age  int
    }
    
    func main() {
        list := make([]Element, 3)
        list[0] = 1       //an int
        list[1] = "Hello" //a string
        list[2] = Person{"mike", 18}
    
        for index, element := range list {
            switch value := element.(type) {
            case int:
                fmt.Printf("list[%d] is an int and its value is %d\n", index, value)
            case string:
                fmt.Printf("list[%d] is a string and its value is %s\n", index, value)
            case Person:
                fmt.Printf("list[%d] is a Person and its value is [%s, %d]\n", index, value.name, value.age)
            default:
                fmt.Println("list[%d] is of a different type", index)
            }
        }
    }

    参考资料

    GoWeb编程: https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/02.6.md

    20180210174507305

    展开全文
  • 面向对象六大原则

    万次阅读 多人点赞 2015-11-30 00:10:44
    小民的主管是个工作经验丰富的技术专家,对于小民的工作并不是很满意,尤其小民最薄弱的面向对象设计,而Android开发又是使用Java语言,什么抽象、接口、六大原则、23种设计模式等名词把小民弄得晕头转向。...
  • 面向对象基本概念

    万次阅读 多人点赞 2019-02-06 21:56:15
    面向对象就是:把数据及对数据的操作方法放在一起,作为一个相互依存的整体——对象。对同类对象抽象出其共性,形成类。类中的大多数数据,只能用本类的方法进行处理。类通过一个简单的外部接口与外界发生关系,对象...
  • 本文将对Java程序设计的对象和类进行深入详细介绍,主要涉及以下内容: - 面向对象程序设计 - 如何创建标准Java类库中的类对象 - 如何编写自己的类
  • 因为想在笔记中夹杂这篇文章中部分内容,所以进行了还是比较多的引用,核心的地方还是自己写的 可以一直接调转到深入理解Java的OOP ...名称:Object-Oriented Analysis:面向对象分析方法 OOA是指...
  • 行为委托

    千次阅读 2016-06-03 21:23:02
    我们现在深入发掘一下javaScript中对象的[[Prototype]]机制到底是什么。首先回顾一下一个结论:[[Prototype]]机制就是指对象中的一个内部链接引用另一个对象。 如果在第一个对象上没有找到需要的属性或者方法引用,...
  • JavaScript - 实例对象 与 new命令

    千次阅读 2020-05-18 16:01:23
    1.应用场景 JavaScript 语言具有很强的面向对象编程能力, ... 典型的面向对象编程语言(比如 C++ 和 Java),都有“类”(class)这个概念。所谓“类”就是对象的模板,对象就是“类”的实例。 .
  • Java面向对象面试题总结

    千次阅读 2019-02-27 17:22:05
    (2)提供一个接口来描述其他对象的使用方法 (3)其他对象不能直接修改本对象所拥有的属性和方法 (4)封装反映了事物的相对独立性  (5)封装在编程上的作用是使对象以外的部分不能随意存取对象的内部数据...
  • SWMM对象模型

    千次阅读 2018-09-26 14:46:08
    图1-1 典型的城市排水系统图(来自EPA) 上图描绘了典型的城市排水系统所包含的要素。SWMM将该系统进行概化为几个主要环境体之间的一系列水流和物质流。这些环境体包括如下: 大气环境体产生降水并将污染物沉积到...
  • ”状态的对象行为模式 摘 要   在 理论上,使应用多线程化可以改善性能(通过同时执行多个指令流),并简化程序结构(通过允许每个线程同步地、而不是反应式地或异步地执行)。而在实践中, 由于获取和释放...
  • 编写典型交互行为脚本(依据用例描述) 从脚本中提取事件及相关对象,用顺序图表达 确定对象状态及状态间转换关系,用状态图描绘 结合ATM系统的实例,介绍建立动态模型的方法 第一步编写脚本 脚本描述用户与目标系统...
  • Java实现面向对象编程

    万次阅读 2018-07-17 16:18:06
    1.1用面向对象设计电子宠物系统... 14 1.1.1为什么使用面向对象... 14 1.1.2使用面向对象进行设计... 15 1.2通过创建对象实现领养宠物功能... 17 1.2.1创建类的对象... 17 1.2.2构造方法及其重载... 23 1.2.3...
  • 面向对象思想

    万次阅读 2018-10-15 09:47:25
    符合开闭原则最典型的设计模式是装饰者模式,它可以动态地将责任附加到对象上,而不用去修改类的代码。 3. 里氏替换原则 子类对象必须能够替换掉所有父类对象。 继承是一种 IS-A 关系,子类需要能够当成...
  • Java引用对象

    千次阅读 2018-12-11 10:09:03
    你也许想知道循环引用会发生什么,即对象A包含一个对象B的引用,同时对象B也包含对象A的引用。答案是标记-清除回收器并不傻,如果A和B都无法由强引用链到达,那么它们都可以被回收。 Finalizers C++允许对象...
  • 设计模式 | 责任链模式及典型应用

    千次阅读 2018-10-31 23:00:54
    一个事件需要经过多个对象处理是一个挺常见的场景,譬如采购审批流程,请假流程,软件开发中的异常处理流程,web请求处理流程等各种各样的流程,可以考虑使用责任链模式来实现。 以请假流程为例,一般公司普通员工的...
  • 面向对象分析与设计

    千次阅读 2020-07-03 19:27:35
    用户无需知道对象内部的细节,但可以通过对象对外提供的接口来访问该对象。 优点: 减少耦合:可以独立地开发、测试、优化、使用、理解和修改 减轻维护的负担:可以更容易被程序员理解,并且在调试的时候可以不影响...
  • ☞ 面向对象就是把构成问题事物分解成多个对象,建立对象不是为了完成某个步骤,而是描述某个事物在这个解决问题的步骤中的行为。 1.面向对象是一种思维方法 2.面向对象是一种编程方法 3.面向对象并不只针对某一...
  • 面向对象编程(Python版详解)

    千次阅读 多人点赞 2020-04-03 14:14:18
    文章目录一.面向对象编程介绍二.类和对象三....面向对象则出现得更晚一些,典型代表为Java或C++等语言,更加适合用于大型开发场景。两种开发思想各有长短。 对于面向过程的思想: 需要实现一个功能的...
  • 对象结构型模式

    万次阅读 2019-11-27 21:55:46
    结构型模式(Structural Pattern)描述如何将类或者对象结合在一起形成更大的结构 适配器模式 在适配器模式中可以定义一个包装类,包装不兼容接口的对象,这个包装类指的就是适配器(Adapter),它所包装的对象就是...
  • ... 这个对象不是C#中的实例,C#中我们把一个类的实例也叫做对象,这种对象严格的说应该是面向对象的编程实现(OOP)中的对象,面向对象编程,也不是面向类的实例编程。对象的定义是人们要进行研
  • 数据结构与对象的区别

    千次阅读 2014-04-04 12:47:28
    最常见的应用在分布式服务,以wcf,webservice,reset之类的分布式服务中不可或缺的数据传输对象(DTO)模式,DTO(Request/Response)就是一个很典型的数据载体,只存在简单的get,set属性,并且更倾向于
  • 面向对象建模的三种模型

    千次阅读 2015-07-10 19:01:00
    描述的是系统内部的组成元素--对象的特征,包括属性和行为。它是一种静态的描述。 状态模型: 描述对象在系统交互过程中所产生的状态的变化。 交互模型: 描述对象对象之间信息的交流。 转载于:...
  • 使用终结方法会导致行为不稳定,降低性能,以及可移植性的问题,当然,终结方法也有其可用之处。但是根据经验,应该避免使用终结方法。 终结方法的缺点: 终结方法不能保证会被及时的执行。当一个对象变得不可...
  • C#面向对象经典资料

    千次阅读 2012-09-04 17:42:04
    对象行为则由对象的方法和接口定义。对象通过classe和struts定义。对象通过标识来区分是否相同。对象都是从类和结构中定义的模板实例化得到。均继承于Object类。 2、类 类定义了数据类型的数据和行为。可以根据...
  • 面向对象的分析方法

    千次阅读 2015-05-11 21:55:16
    是在一个系统的开发过程中进行了系统业务调查以后,按照面向对象的思想来分析问题。OOA与结构化分析有较大的区别。OOA所强调的是在系统调查资料的基础上,针对OO方法所需要的素材进行的归类分析和整理,而不是对管理...
  • Java语言中的面向对象特性 【课前思考】  1. 什么是对象?什么是类?什么是包?什么是接口?什么是内部类?  2. 面向对象编程的特性有哪三个?它们各自又有哪些特性?  3...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 88,443
精华内容 35,377
关键字:

对象典型行为描述