精华内容
下载资源
问答
  • 面向对象——对象行为(方法)

    千次阅读 2015-09-09 23:11:33
    方法调用: 1. 一个方法调用时,将导致控制流程转到调用的方法并执行方法中的语句; 2. 在执行方法中的语句时...① Java是纯面向对象语言,Java中的方法只能出现在类里面; ② 在Java中,没有声明为静态的方法只

    方法调用:

    1. 一个方法被调用时,将导致控制流程转到被调用的方法并执行方法中的语句;

    2. 在执行方法中的语句时,如果又有其他方法被调用,将导致控制流程转到其他方法并执行方法中的语句;

    3. 当方法中的语句执行完成,控制流程将回到调用方法处。继续执行方法后面的其他语句。

    注意:

    ① Java是纯面向对象语言,Java中的方法只能出现在里面;

    ② 在Java中,没有声明为静态的方法只能通过类实例化对象的方式调用;

    ③ 如果想编写一个不需要类实例化对象的方法,我们需要使用静态方法。


    按值调用<实参和形参>

    概念:

    当实际参数传递给形式参数时,实际参数数据被复制(拷贝)给形式参数的过程。

    而且,不管传递给方法的实际参数是什么类型,相关的形式参数都会得到该数据的一份拷贝。<无论实参是什么类型,形参都会接收到数据>

    引用类型传递:

    如果实参是引用类型,按值传递的是对象的引用(地址),而不是对象被传入。这样,实参和形参都引用同一个对象。


    方法重载<不看方法的返回值类型>

    概念:

    当有两个或多个类同名,但是有不同参数列表的方法时。<根据:参数数据类型,参数个数,参数的顺序>

    作用:

    实现功能类似而所处理的数据类型不同的代码简化,方便了程序员调用。体现了面向对象的优越性。


    构造器(构造函数) <用于初始化属性>

    在Java程序中,程序如果不显示定义构造器,那么编译器会在编译时,自动添加一个无参的构造器。

    这就是即使我们没有显示定义构造器,仍然可以实例化对象的原因。


    但是,如果程序员显示定义构造器后,编译器在编译时,就不会自动添加无参构造器;

    因此,如果定义了带参数的构造器后,无参的构造器需要显示定义,否则无法使用。

    注意:

    ① 一个特殊方法,类实例化后,自动被调用执行;

    ② 初始化类的实例;

    ③ 构造器的名称必须要与类名相同

    ④ 是一个没有返回值的方法

    ⑤ 构造器可以重载,也可以有多个构造器。


    this关键字 <返回调用当前方法的对象引用>

    作用:

    1. 命名冲突,成员变量(属性)和方法名的冲突;

    2. 可以通过 this 在一个构造器内,调用另一个构造器。

    注意:

    1. 调用时,必须放在构造器的第一个语句;

    2. 一个构造器最多只能调用一个构造器;

    3. 不能在构造器以外的任何方法中调用构造器。



    展开全文
  • 设计模式 ( 十八 ) 策略模式Strategy(对象行为型)

    万次阅读 多人点赞 2012-05-12 15:50:25
    设计模式 ( 十八 ) 策略模式Strategy(对象行为型) 1.概述  在软件开发中也常常遇到类似的情况,实现某一个功能有多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能。如查找...

    设计模式 ( 十八 ) 策略模式Strategy(对象行为型)

    1.概述

            在软件开发中也常常遇到类似的情况,实现某一个功能有多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能。如查找、排序等,一种常用的方法是硬编码(Hard Coding)在一个类中,如需要提供多种查找算法,可以将这些算法写到一个类中,在该类中提供多个方法,每一个方法对应一个具体的查找算法;当然也可以将这些查找算法封装在一个统一的方法中,通过if…else…或者case等条件判断语句来进行选择。这两种实现方法我们都可以称之为硬编码,如果需要增加一种新的查找算法,需要修改封装算法类的源代码;更换查找算法,也需要修改客户端调用代码。在这个算法类中封装了大量查找算法,该类代码将较复杂,维护较为困难。如果我们将这些策略包含在客户端,这种做法更不可取,将导致客户端程序庞大而且难以维护,如果存在大量可供选择的算法时问题将变得更加严重。

    例子1:一个菜单功能能够根据用户的“皮肤”首选项来决定是否采用水平的还是垂直的排列形式。同事可以灵活增加菜单那的显示样式。

    例子2:出行旅游:我们可以有几个策略可以考虑:可以骑自行车,汽车,做火车,飞机。每个策略都可以得到相同的结果,但是它们使用了不同的资源。选择策略的依据是费用,时间,使用工具还有每种方式的方便程度 。



    2.问题

    如何让算法和对象分开来,使得算法可以独立于使用它的客户而变化?

    3.解决方案

    策略模式义一系列的算法,把每一个算法封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。也称为政策模式(Policy)。(Definea family of algorithms,encapsulate each one, andmake them interchangeable. Strategy lets the algorithmvary independently from clients that use it. 

    策略模式把对象本身和运算规则区分开来,其功能非常强大,因为这个设计模式本身的核心思想就是面向对象编程的多形性的思想。

    4.适用性

    当存在以下情况时使用Strategy模式
    1)• 许多相关的类仅仅是行为有异。 “策略”提供了一种用多个行为中的一个行为来配置一个类的方法。即一个系统需要动态地在几种算法中选择一种。
    2)• 需要使用一个算法的不同变体。例如,你可能会定义一些反映不同的空间 /时间权衡的算法。当这些变体实现为一个算法的类层次时 ,可以使用策略模式。
    3)• 算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构。
    4)• 一个类定义了多种行为 , 并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移入它们各自的Strategy类中以代替这些条件语句。

    5.结构


    6.模式的组成

    环境类(Context):用一个ConcreteStrategy对象来配置。维护一个对Strategy对象的引用。可定义一个接口来让Strategy访问它的数据。
    抽象策略类(Strategy):定义所有支持的算法的公共接口。 Context使用这个接口来调用某ConcreteStrategy定义的算法。
    具体策略类(ConcreteStrategy):以Strategy接口实现某具体算法。

    7.效果

    Strategy模式有下面的一些优点:
    1) 相关算法系列 Strategy类层次为Context定义了一系列的可供重用的算法或行为。 继承有助于析取出这些算法中的公共功能。
    2) 提供了可以替换继承关系的办法: 继承提供了另一种支持多种算法或行为的方法。你可以直接生成一个Context类的子类,从而给它以不同的行为。但这会将行为硬行编制到 Context中,而将算法的实现与Context的实现混合起来,从而使Context难以理解、难以维护和难以扩展,而且还不能动态地改变算法。最后你得到一堆相关的类 , 它们之间的唯一差别是它们所使用的算法或行为。 将算法封装在独立的Strategy类中使得你可以独立于其Context改变它,使它易于切换、易于理解、易于扩展。
    3) 消除了一些if else条件语句 :Strategy模式提供了用条件语句选择所需的行为以外的另一种选择。当不同的行为堆砌在一个类中时 ,很难避免使用条件语句来选择合适的行为。将行为封装在一个个独立的Strategy类中消除了这些条件语句。含有许多条件语句的代码通常意味着需要使用Strategy模式。
    4) 实现的选择 Strategy模式可以提供相同行为的不同实现。客户可以根据不同时间 /空间权衡取舍要求从不同策略中进行选择。

    Strategy模式缺点:

    1)客户端必须知道所有的策略类,并自行决定使用哪一个策略类:  本模式有一个潜在的缺点,就是一个客户要选择一个合适的Strategy就必须知道这些Strategy到底有何不同。此时可能不得不向客户暴露具体的实现问题。因此仅当这些不同行为变体与客户相关的行为时 , 才需要使用Strategy模式。
    2 ) Strategy和Context之间的通信开销 :无论各个ConcreteStrategy实现的算法是简单还是复杂, 它们都共享Strategy定义的接口。因此很可能某些 ConcreteStrategy不会都用到所有通过这个接口传递给它们的信息;简单的 ConcreteStrategy可能不使用其中的任何信息!这就意味着有时Context会创建和初始化一些永远不会用到的参数。如果存在这样问题 , 那么将需要在Strategy和Context之间更进行紧密的耦合。
    3 )策略模式将造成产生很多策略类:可以通过使用享元模式在一定程度上减少对象的数量。 增加了对象的数目 Strategy增加了一个应用中的对象的数目。有时你可以将 Strategy实现为可供各Context共享的无状态的对象来减少这一开销。任何其余的状态都由 Context维护。Context在每一次对Strategy对象的请求中都将这个状态传递过去。共享的 Strategy不应在各次调用之间维护状态。

    8.实现

    1)出行旅游:

    uml:


    代码实现:

    <?php
    /**
    * 策略模式
    * 定义一系列的算法,把每一个算法封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化
    *
    */ 
    
    
    /**
    * 出行旅游
    *
    * 
    */
    interface TravelStrategy{
    	public function travelAlgorithm();
    } 
    
    
    /**
     * 具体策略类(ConcreteStrategy)1:乘坐飞机
     */
    class AirPlanelStrategy implements TravelStrategy {
    	public function travelAlgorithm(){
    		echo "travel by AirPlain", "<BR>\r\n"; 
    	}
    } 
    
    
    /**
     * 具体策略类(ConcreteStrategy)2:乘坐火车
     */
    class TrainStrategy implements TravelStrategy {
    	public function travelAlgorithm(){
    		echo "travel by Train", "<BR>\r\n"; 
    	}
    } 
    
    /**
     * 具体策略类(ConcreteStrategy)3:骑自行车
     */
    class BicycleStrategy implements TravelStrategy {
    	public function travelAlgorithm(){
    		echo "travel by Bicycle", "<BR>\r\n"; 
    	}
    } 
    
    
    
    /**
     * 
     * 环境类(Context):用一个ConcreteStrategy对象来配置。维护一个对Strategy对象的引用。可定义一个接口来让Strategy访问它的数据。
     * 算法解决类,以提供客户选择使用何种解决方案:
     */
    class PersonContext{
    	private $_strategy = null;
    
    	public function __construct(TravelStrategy $travel){
    		$this->_strategy = $travel;
    	}
    	/**
    	* 旅行
    	*/
    	public function setTravelStrategy(TravelStrategy $travel){
    		$this->_strategy = $travel;
    	}
    	/**
    	* 旅行
    	*/
    	public function travel(){
    		return $this->_strategy ->travelAlgorithm();
    	}
    } 
    
    // 乘坐火车旅行
    $person = new PersonContext(new TrainStrategy());
    $person->travel();
    
    // 改骑自行车
    $person->setTravelStrategy(new BicycleStrategy());
    $person->travel();
    
    ?> 
    
    
    

     

    2)排序策略:某系统提供了一个用于对数组数据进行操作的类,该类封装了对数组的常见操作,

    如查找数组元素、对数组元素进行排序等。现以排序操作为例,使用策略模式设计该数组操作类,

    使得客户端可以动态地更换排序算法,可以根据需要选择冒泡排序或选择排序或插入排序,

    也能够灵活地增加新的排序算法。

    9.与其他相关模式

    1)状态模式

    策略模式和其它许多设计模式比较起来是非常类似的。策略模式和状态模式最大的区别就是策略模式只是的条件选择只执行一次,而状态模式是随着实例参数(对象实例的状态)的改变不停地更改执行模式。换句话说,策略模式只是在

    对象初始化的时候更改执行模式,而状态模式是根据对象实例的周期时间而动态地改变对象实例的执行模式。

    可以通过环境类状态的个数来决定是使用策略模式还是状态模式。
    策略模式的环境类自己选择一个具体策略类,具体策略类无须关心环境类;而状态模式的环境类由于外在因素需要放进一个具体状态中,
    以便通过其方法实现状态的切换,因此环境类和状态类之间存在一种双向的关联关系。
    使用策略模式时,客户端需要知道所选的具体策略是哪一个,而使用状态模式时,客户端无须关心具体状态,环境类的状态会根据用户的操作自动转换。
    如果系统中某个类的对象存在多种状态,不同状态下行为有差异,而且这些状态之间可以发生转换时使用状态模式
    如果系统中某个类的某一行为存在多种实现方式,而且这些实现方式可以互换时使用策略模式

    2)简单工厂的区别:点击打开链接

    工厂模式是创建型模式 ,它关注对象创建,提供创建对象的接口. 让对象的创建与具体的使用客户无关。
    策略模式是对象行为型模式 ,它关注行为和算法的封装 。它定义一系列的算法,把每一个算法封装起来, 并且使它们可相互替换。使得算法可独立于使用它的客户而变化

    用我们上面提到旅行的例子:
    我们去旅行。策略模式的做法:有几种方案供你选择旅行,选择火车好呢还是骑自行车,完全有客户自行决定去构建旅行方案(比如你自己需要去买火车票,或者机票)。而工厂模式是你决定哪种旅行方案后,不用关注这旅行方案怎么给你创建,也就是说你告诉我方案的名称就可以了,然后由工厂代替你去构建具体方案(工厂代替你去买火车票)。

    上面的例子里面client代码:
    $person = new PersonContext(new TrainStrategy());
    $person->travel();
    我们看到客户需要自己去创建具体旅行(new TrainStrategy())实例。传递的是具体实例。
    而工厂模式你只要告诉哪种旅行就可以了,不是传递一个具体实例,而是一个标识(旅行方案标识)。

    10.总结与分析

    1)策略模式是一个比较容易理解和使用的设计模式,策略模式是对算法的封装它把算法的责任和算法本身分割开委派给不同的对象管理。策略模式通常把一个系列的算法封装到一系列的策略类里面,作为一个抽象策略类的子类。用一句话来说,就是“准备一组算法,并将每一个算法封装起来,使得它们可以互换”。
    2)在策略模式中,应当由客户端自己决定在什么情况下使用什么具体策略角色。2)
    3)策略模式仅仅封装算法,提供新算法插入到已有系统中以及老算法从系统中“退休”的方便,策略模式并不决定在何时使用何种算法,算法的选择由客户端来决定。这在一定程度上提高了系统的灵活性,但是客户端需要理解所有具体策略类之间的区别,以便选择合适的算法,这也是策略模式的缺点之一,在一定程度上增加了客户端的使用难度。

    转载指明原文出处:hguisu   设计模式 ( 十八 ) 策略模式Strategy(对象行为型) http://blog.csdn.net/hguisu/article/details/7558249






    感谢您的支持,我会继续努力的! 扫码打赏,你说多少就多少

             
    展开全文
  • 设计模式 ( 十五 ) 中介者模式Mediator(对象行为型) 1.概述 在面向对象的软件设计与开发过程中,根据“单一职责原则”,我们应该尽量将对象细化,使其只负责或呈现单一的职责,即将行为分布到各个对象中。...

    设计模式 ( 十五 ) 中介者模式Mediator(对象行为型)

    1.概述

    在面向对象的软件设计与开发过程中,根据“单一职责原则”,我们应该尽量将对象细化,使其只负责或呈现单一的职责,即将行为分布到各个对象中。

    对于一个模块或者系统,可能由很多对象构成,而且这些对象之间可能存在相互的引用,在最坏的情况下,每一个对象都知道其他所有的对象,这无疑复杂化了对象之间的联系。虽然将一个系统分割成许多对象通常可以增强可复用性,但是对象间相互连接的激增又会降低其可复用性,大量的相互连接使得一个对象似乎不太可能在没有其他对象的支持下工作,系统表现为一个不可分割的整体,而且对系统的行为进行任何较大的改动都会十分困难。结果是你不得不定义大量的子类以定制系统的行为。因此,为了减少对象两两之间复杂的引用关系,使之成为一个松耦合的系统,我们需要使用中介者模式.
    例子1:

    2.问题

    面对一系列的相交互对象。怎么样保证使各对象不需要显式地相互引用,使其耦合松散?

    3.解决方案

    中介者模式:用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。中介者模式又称为调停者模式。(Define an object thatencapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects fromreferring to each other explicitly, and it lets you vary their interaction independently

    4.适用性

    在下列情况下使用中介者模式:

    • 1)系统中对象之间存在复杂的引用关系,产生的相互依赖关系结构混乱且难以理解。
    • 2)一组对象以定义良好但是复杂的方式进行通信。产生的相互依赖关系结构混乱且难以理解。
    • 3)一个对象引用其他很多对象并且直接与这些对象通信 ,导致难以复用该对象。
    • 4)想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。可以通过引入中介者类来实现,在中介者中定义对象交互的公共行为,如果需要改变行为则可以增加新的中介者类。

    5.结构


    6.模式的组成

    抽象中介者(Mediator):中介者定义一个接口用于与各同事(Colleague)对象通信。
    具体中介者(ConcreteMediator): 具体中介者通过协调各同事对象实现协作行为。了解并维护它的各个同事。
    抽象同事类(Colleague class): 定义同事类接口,定义各同事的公有方法.
    具体同事类(ConcreteColleague): 实现抽象同事类中的方法。每一个同时类需要知道中介者对象;每个具体同事类只需要了解自己的行为,而不需要了解其他同事类的情况。每一个同事对象在需与其他的同事通信的时候,与它的中介者通信。

    7.效果

    中介者模式的优点:
    1) 减少了子类生成:  Mediator将原本分布于多个对象间的行为集中在一起。改变这些行为只需生成Mediator的子类即可。这样各个Colleague类可被重用。
    2) 简化各同事类的设计和实现 : 它将各同事类Colleague解耦,Mediator有利于各Colleague间的松耦合. 你可以独立的改变和复用各Colleague类和Mediator类。
    3) 它简化了对象协议: 用Mediator和各Colleague间的一对多的交互来代替多对多的交互。一对多的关系更易于理解、维护和扩展。
    4) 它对对象如何协作进行了抽象 将中介作为一个独立的概念并将其封装在一个对象中,使你将注意力从对象各自本身的行为转移到它们之间的交互上来。这有助于弄清    楚一个系统中的对象是如何交互的。
    5) 它使控制集中化 中介者模式将交互的复杂性变为中介者的复杂性。
    中介者模式的缺点:
    因为中介者封装了协议,即在具体中介者类中包含了同事之间的交互细节,可能会导致具体中介者类非常复杂,这可能使得中介者自身成为一个难于维护的
    庞然大物。

    8.实现

    <?php
    
    /**
     * 中介者模式
     *
     * 
    */
    /**
     * 抽象中介者类
     */
    abstract class Mediator
    {
    	static protected  $_colleaguesend = array(
    										'ConcreteColleague1'=> 'ConcreteColleague2',
    										'ConcreteColleague2'=> 'ConcreteColleague3',
    										'ConcreteColleague3'=> 'ConcreteColleague1',
    										);
    	protected  $_colleagues = null; //array
    	public  function register(Colleague $colleague) {
    		$this->_colleagues[get_class($colleague)] = $colleague;
    	}
    
    	public abstract function operation($name, $message);
    }
    /**
     * 具体中介者类
     */
    class ConcreteMediator extends Mediator
    {
    	
    	public function operation($obj, $message) {
    		$className = self::$_colleaguesend[get_class($obj)];
    		if ($className == get_class($obj) ) {
    			return ;
    		}
    		if ($this->_colleagues[$className]) {
    			
    			$this->_colleagues[$className]->notify($message);
    		}	
    		return ;
    	}
    }
    /**
     * 抽象同事类
     */
    abstract class Colleague
    {
    	protected  $_mediator = null;
    
    	public function __construct($mediator) {
    
    		$this->_mediator = $mediator;
    		$mediator->register($this);
    	}
    	/**
    	 * 通过中介实现相互调用
    	 */
    	public abstract function send($message);
    	/**
    	 * 具体需要实现的业务逻辑代码
    	 */
    	public abstract function notify($message);
    }
    
    /**
     * 具体同事类
     */
    class ConcreteColleague1 extends Colleague
    {
    	public function __construct(Mediator $mediator) {
    		parent::__construct($mediator);
    	}
    
    	public function send($message) {
    		$this->_mediator->operation($this, $message);
    	}
    	
    	public function notify($message) {
    		echo 'ConcreteColleague1 m:', $message, '<br/>';
    	}
    
    }
    
    /**
     * 具体同事类
     */
    class ConcreteColleague2 extends Colleague
    {
    	public function __construct(Mediator $mediator) {
    		parent::__construct($mediator);
    	}
    
    	public function send($message) {
    		$this->_mediator->operation($this, $message);
    	}
    	public function notify($message) {
    		echo 'ConcreteColleague2 m:', $message, '<br/>';
    	}
    	
    }
    
    
    /**
     * 具体同事类
     */
    class ConcreteColleague3 extends Colleague
    {
    	public function __construct(Mediator $mediator) {
    		parent::__construct($mediator);
    	}
    
    	public function send($message) {
    		$this->_mediator->operation($this, $message);
    	}
    	public function notify($message) {
    		echo 'ConcreteColleague3 m:', $message, '<br/>';
    	}
    	
    }
    $objMediator = new  ConcreteMediator();
    $objC1 = new ConcreteColleague1($objMediator);
    $objC2 = new ConcreteColleague2($objMediator);
    $objC3 = new ConcreteColleague3($objMediator);
    
    $objC1->send("from ConcreteColleague1");
    $objC2->send("from ConcreteColleague2");
    $objC3->send("from ConcreteColleague3");
    /****************************************************/
    


    9.与其他相关模式

    1)外观模式,Facade与中介者的不同之处在于它是对一个对象子系统进行抽象,从而提供了一个为方便的接口。它的协议是单向的,即 Facade对象对这个子系统类提出请求,但反之则不。相反,Mediator提供了各Colleague对象不支持或不能支持的协作行为,而且协议是多向。
    2) Colleague可使用Observers模式与Mediator通信。

    10.总结与分析

    1)迪米特法则的一个典型应用:在中介者模式中,通过创造出一个中介者对象,将系统中有关的对象所引用的其他对象数目减少到最少,使得一个对象与其同事之间的相互作用被这个对象与中介者对象之间的相互作用所取代。因此,中介者模式就是迪米特法则的一个典型应用
    2) 通过引入中介者对象,可以将系统的网状结构变成以中介者为中心的星形结构,中介者承担了中转作用和协调作用。中介者类是中介者模式的核心,它对整个系统进行控制和协调,简化了对象之间的交互,还可以对对象间的交互进行进一步的控制。
    3) 中介者模式的主要优点在于简化了对象之间的交互,将各同事解耦,还可以减少子类生成,对于复杂的对象之间的交互,通过引入中介者,可以简化各同事类的设计和实现;中介者模式主要缺点在于具体中介者类中包含了同事之间的交互细节,可能会导致具体中介者类非常复杂,使得系统难以维护。
    4) 中介者模式适用情况包括:系统中对象之间存在复杂的引用关系,产生的相互依赖关系结构混乱且难以理解;一个对象由于引用了其他很多对象并且直接和这些对象通信,导致难以复用该对象;想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类

    展开全文
  • 设计模式 ( 十三 ) 命令模式Command(对象行为型) 1.概述  在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道请求的操作是哪个,我们只需在程序运行时指定具体的...

    设计模式 ( 十三 ) 命令模式Command(对象行为型)

    1.概述

            在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,我们只需在程序运行时指定具体的请求接收者即可,此时,可以使用命令模式来进行设计,使得请求发送者与请求接收者消除彼此之间的耦合,让对象之间的调用关系更加灵活。

     例子1:电视机遥控器 : 遥控器是请求的发送者,电视机是请求的接收者,遥控器上有一些按钮如开,关,换频道等按钮就是具体命令,不同的按钮对应电视机的不同操作。

    2.问题

          在软件系统中,“行为请求者”与“行为实现者”通常呈现一种“紧耦合”。但在某些场合,比如要对行为进行“记录、撤销/重做、事务”等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将“行为请求者”与“行为实现者”解耦?

    3.解决方案

     命令模式(Command Pattern):将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化对请求排队或者记录请求日志,以及支持可撤销的操作。命令模式又称为动作(Action)模式或事务(Transaction)模式。(Command Pattern: Encapsulate a request asan object, thereby letting youparameterize clients withdifferent requests,queueor log requests,andsupportundoable operations

    4.适用性

    1)系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。

    2)系统需要在不同的时间指定请求、将请求排队和执行请求。

    3)系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作。

    4)系统需要将一组操作组合在一起,即支持宏命令。

    5.结构
    6.模式的组成

    抽象命令类(Command): 声明执行操作的接口。调用接收者相应的操作,以实现执行的方法Execute。

    具体命令类(ConcreteCommand): 创建一个具体命令对象并设定它的接收者。通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。 

    调用者(Invoker): 要求该命令执行这个请求。通常会持有命令对象,可以持有很多的命令对象。

    接收者(Receiver): 知道如何实施与执行一个请求相关的操作。任何类都可能作为一个接收者,只要它能够实现命令要求实现的相应功能。 

    客户类(Client): 创建具体的命令对象,并且设置命令对象的接收者。真正使用命令的客户端是从Invoker来触发执行。 

    7.效果

    Command模式优点:

    1) 降低系统的耦合度:Command模式将调用操作的对象与知道如何实现该操作的对象解耦。

    2) Command是头等的对象。它们可像其他的对象一样被操纵和扩展。

    3) 组合命令:你可将多个命令装配成一个组合命令,即可以比较容易地设计一个命令队列和宏命令。一般说来,组合命令是Composite模式的一个实例。

    4) 增加新的Command很容易,因为这无需改变已有的类。

    5)可以方便地实现对请求的Undo和Redo。

    命令模式的缺点:

    使用命令模式可能会导致某些系统有过多的具体命令类。因为针对每一个命令都需要设计一个具体命令类,因此某些系统可能需要大量具体命令类,这将影响命令模式的使用。

    8.实现

    电视机遥控器 :

    电视机是请求的接收者,

     遥控器是请求的发送者,

     遥控器上有一些按钮,不同的按钮对应电视机的不同操作。抽象命令角色由一个命令接口来扮演,

     有三个具体的命令类实现了抽象命令接口,这三个具体命令类分别代表三种操作:打开电视机、关闭电视机和切换频道。

     显然,电视机遥控器就是一个典型的命令模式应用实例。

    <?php
    /**
     * 电视机遥控器 :
       电视机是请求的接收者,
       遥控器是请求的发送者,
       遥控器上有一些按钮,不同的按钮对应电视机的不同操作。抽象命令角色由一个命令接口来扮演,
       有三个具体的命令类实现了抽象命令接口,这三个具体命令类分别代表三种操作:打开电视机、关闭电视机和切换频道。
       显然,电视机遥控器就是一个典型的命令模式应用实例。
    
     */
    /**
     * The Command abstraction( 命令接口,声明执行的操作).  
     * In this case the implementation must return a result,  
     * sometimes it only has side effects.  
     */
    interface ICommand
    {
    	/**
    	 * 执行命令对应的操作
    	 *
    	 * @param unknown_type $name
    	 * @param unknown_type $args
    	 */
    	function execute();
    }
    
    
    /**
     * ConcreteCommand具体的命令实现对象:打开命令
     */
    class ConcreteCommandOpen implements ICommand {
    	/**
         * 持有相应的接收者对象
         */
    	private  $_receiverTV = null; //
    	/**
         * 示意,命令对象可以有自己的状态
         */
    	private  $_state;
    	/**
         * 构造方法,传入相应的接收者对象
         * @param receiver 相应的接收者对象
         */
    	public function  __construct($receiver){
    		$this->_receiverTV = $receiver;
    	}
    	public function execute() {
    		//通常会转调接收者对象的相应方法,让接收者来真正执行功能
    		$this->_receiverTV->actionOpen();
    	}
    }
    /**
     * ConcreteCommand具体的命令实现对象:关闭
     */
    class ConcreteCommandClose implements ICommand {
    	/**
         * 持有相应的接收者对象
         */
    	private  $_receiverTV = null; //
    	/**
         * 示意,命令对象可以有自己的状态
         */
    	private  $_state;
    	/**
         * 构造方法,传入相应的接收者对象
         * @param receiver 相应的接收者对象
         */
    	public function  __construct($receiver){
    		$this->_receiverTV = $receiver;
    	}
    	public function execute() {
    		//通常会转调接收者对象的相应方法,让接收者来真正执行功能
    		$this->_receiverTV->actionClose();
    	}
    }
    
    /**
     * ConcreteCommand具体的命令实现对象:换频道
     */
    class ConcreteCommandChange implements ICommand {
    	/**
         * 持有相应的接收者对象
         */
    	private  $_receiverTV = null; //
    	/**
         * 示意,命令对象可以有自己的状态
         */
    	private  $_state;
    	/**
         * 构造方法,传入相应的接收者对象
         * @param receiver 相应的接收者对象
         */
    	public function  __construct($receiver){
    		$this->_receiverTV = $receiver;
    	}
    	public function execute() {
    		//通常会转调接收者对象的相应方法,让接收者来真正执行功能
    		$this->_receiverTV->actionChange();
    	}
    }
    
    /**
     * 接收者对象
     */
    class ReceiverTV {
    	/**
         * 真正执行命令相应的打开操作
         */
    	public function actionOpen(){
    		echo 'actionOpen<br/>';
    	}
    	
    	/**
         * 真正执行命令相应的关闭操作
         */
    	public function actionClose(){
    		echo 'actionClose<br/>';
    	}
    	
    	/**
         *  真正执行命令相应的换频道操作
         */
    	public function actionChange(){
    		echo 'actionChange<br/>';
    	}
    }
    
    /**
     * 调用者Invoker:遥控器 
     */
    class InvokerControler {
    	/**
         * 持有命令对象
         */
    	private $_commands = null; //ICommand
    	/**
         * 设置调用者持有的命令对象
         * @param command 命令对象
         */
    	public function addCommand($command) {
    		$classname = get_class($command);
    		$this->_commands[$classname] = $command;
    	}
    	/**
         * 示意方法,要求命令执行请求
         */
    	public function runCommand($cmdName) {
    		//调用命令对象的执行方法
    		$this->_commands[$cmdName]->execute();
    	}
    }
    class Client {
        /**
         * 示意,负责创建命令对象,并设定它的接收者
         */
        public static  function main(){
           //创建电视接收者
           $receiver = new ReceiverTV();
           
           //创建Invoker
           $invoker = new InvokerControler();
           //创建命令对象,设定它的接收者
           $commandOpen = new ConcreteCommandOpen($receiver);
           //把命令对象设置进调用遥控器
           $invoker->addCommand($commandOpen);
           
           //执行打开命令
           $invoker->runCommand(get_class($commandOpen));
           
         
        }
    }
    Client::main();
    ?>

    UML图:

    宏命令又称为组合命令,它是命令模式和组合模式联用的产物:
    宏命令也是一个具体命令,不过它包含了对其他命令对象的引用,在调用宏命令的execute()方法时,将递归调用它所包含的每个成员命令的execute()方法,一个宏命令的成员对象可以是简单命令,还可以继续是宏命令。执行一个宏命令将执行多个具体命令,从而实现对命令的批处理。

    Ÿ


    9.与其他相关模式

    1)Composite模式(可被用来实现宏命令。

    2)备忘录Memento模式可用来保持某个状态,命令用这一状态来取消它的效果。在被放入历史表列前必须被拷贝的命令起到一种原型的作用。

    10.总结与分析

    1)命令模式的本质是对命令进行封装将发出命令的责任和执行命令的责任分割开
    2)每一个命令都是一个操作:请求的一方发出请求,要求执行一个操作接收的一方收到请求,并执行操作
    3)命令模式允许请求的一方和接收的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否被执行、何时被执       行,以及是怎么被执行的。
    4)命令模式使请求本身成为一个对象,这个对象和其他对象一样可以被存储和传递。
    5)命令模式的关键在于引入了抽象命令接口,且发送者针对抽象命令接口编程,只有实现了抽象命令接口的具体命令才能与接收者相关联。 


    展开全文
  • 传输对象模式

    千次阅读 2019-09-25 19:58:52
    传输对象被称为数值对象。传输对象是一个具有 getter/setter 方法的简单的 POJO 类,它是可序列化的,所以它可以通过网络传输。它没有任何的行为。服务器端的业务类通常从数据库读取数据,然后填充 POJO,并把它...
  • 在软件开发过程中,对于系统中的某些对象,它们存储在同一个集合collection中,且具有不同的类型,而且对于该集合中的对象,可以接受一类称为访问者的对象来访问,而且不同的访问者其访问方式有所不同。 例子1:...
  • 本文是对于 《设计模式 可复用面向对象软件的基础 Erich Gamma、Richard Helm》一书中的状态模型例子进行实现,并做了一些说明 引目:  考虑一个表示网络连接的类T C P C o n n e c t i o n。一个T C P C ...
  • 类,就是实例化的对象,每个单独的对象都有一个特定的身份和状态。单独的对象是一种组织代码的有用方法,但通常你会处理一组对象或者集合。 集合不一定是均一的。图形用户界面框架中的 Window 对象可以收集任意数量...
  • 1、函数对象(function object)也称为仿函数(functor) 2、一个行为类似函数的对象,它可以没有参数,也可以带有若干参数。 3、任何重载了调用运算符operator()的类的对象都满足函数对象的特征 4、函数对象...
  • Java 销毁对象

    千次阅读 2015-05-16 06:44:49
     在Java中完成这样的工作主要是依靠try-finally机制来协助完成的,然而Java中还提供了另外一种被称为finalizer的机制,使用者仅仅需要重载Object对象提供的finalize方法,这样当JVM的在进行垃圾回收...
  • java面向对象

    万次阅读 多人点赞 2018-08-21 16:51:59
    本文内容是根据毕晓东老师的视频教程总结而得。包括面向对象概念、类与对象的关系、... 面向过程强调的是功能、行为 面向对象:将功能封装进对象,强调具备了功能的对象 面向对象是基于面向过程的 面向过程例子: ...
  • 设计模式之状态模式(行为型)

    千次阅读 2018-12-23 00:04:55
    一个对象在其内部状态改变时改变其行为,这个对象我们可以称为状态对象,所以状态模式是一种对象行为型模式。 模式结构 Context:环境类 Context类也可以称之为上下文类,实际上就是拥有状态的对象,可以理解为...
  • 面向对象的程序设计Java-类和对象

    千次阅读 2017-02-21 15:11:20
    对象(Object) 对象具有两方面的含义 在现实世界中: 是客观世界中的一个实体 在计算机是中: 是一个可标识的存储区域 ...PS:类和对象有时都统称“对象”,为了明确起见,后者称为对象实例” 例如
  • JAVA 入坑教程 | 对象和类

    千次阅读 2017-01-12 16:18:19
    支持以下基本概念:继承封装抽象类对象实例方法重载本节我们重点研究对象和类的概念:对象对象是类的一个实例(对象不是找个女朋友),有状态和行为。例如,一条狗是一个对象,它的状态有:颜色、名字、品种;行为...
  • JAVA面向对象对象和类

    千次阅读 多人点赞 2015-12-20 09:30:41
    Java是一种面向对象的编程语言,面向对象在整个Java的学习中属于重中之重,从这一篇博客开始,将逐步为大家介绍Java面向对象的相关知识,这一偏将为大家介绍对象和类的概念以及如何定义类和创建对象。 一、对象和类...
  • python中的对象的理解

    千次阅读 2018-05-01 16:18:52
    它所具有的行为称为方法(method) Python中的对象包含三要素:id、type、value 其中id用来唯一标识一个对象, type标识对象的类型, value是对象的值 is判断的是a对象是否就是b对象,是通过id来判断的 ==...
  • 对象与引用对象

    千次阅读 2014-06-03 22:16:43
    概念介绍 对象对象引用
  • 类与对象(Java)

    千次阅读 2019-12-29 08:58:03
    对象对象是类的一个实例,有状态和...局部变量:在方法、构造方法或者语句块中定义的变量被称为局部变量。变量声明和初始化都是在方法中,方法结束后,变量就会自动销毁。 成员变量:成员变量是定义在类中,方法...
  • 浅谈一下JAVA对象对象引用以及对象赋值

    万次阅读 多人点赞 2013-09-19 00:50:29
    浅谈一下JAVA对象对象引用以及对象赋值   今天有班级同学问起JAVA对象的引用是什么。正好趁着这次机会,自己总结一下JAVA对象对象引用以及对象赋值。自己总结了所看到的网上相关方面的不少帖子,整理汇总形成...
  • 【C++面向对象学习笔记】-基础知识

    千次阅读 2015-09-08 16:58:53
    1.基本概念 面向对象程序设计是利用...一个对象行为由一组函数定义,对一个对象调用一个函数就是请求对象执行一个任务。 相同类型的对象用一个通用的类来定义。一个类是一个模板或者一个蓝图,它定义了对象具有什么
  • JS除了内置对象之外,还允许我们程序自己定义属于我们自己的对象,在JS中自定义对象的方式有2种:通过构造器创建对象,通过JSON创建对象。 4.7.1 构造器创建对象(原生JS对象) 构造器,就是一个普通的函数,...
  • 分层有限状态机和无人车行为规划...行为规划(Behavior Planning)是无人车规划模块的一层,位于全局任务规划和底层的动作规划层之间,驾驶行为规划也被称为驾驶行为决策,这一层的作用主要是依据来自上层(任务规划...
  • JAVA 面向对象 类和对象

    千次阅读 2016-07-17 15:57:34
    类 可以认为是一种自定义的数据类型. 可以使用类来 定义变量,所有使用类定义的变量都是 引用变量. 它们将会引用到 类的对象. 类用于描述客观世界里 某一类对象的共同特征. 而对象则是 类的具体存在. ...
  • 面向对象基本概念

    万次阅读 多人点赞 2019-02-06 21:56:15
    面向对象就是:把数据及对数据的操作方法放在一起,作为一个相互依存的整体——对象。对同类对象抽象出其共性,形成类。类中的大多数数据,只能用本类的方法进行处理。类通过一个简单的外部接口与外界发生关系,对象...
  • 类和对象之间的关系?封装继承多态?

    千次阅读 2018-03-04 09:19:00
    在面向对象的编程思想中把对象的属性和行为分别称为对象的属性和方法,是构成对象的两个主要因素;在编程中,对象的属性存储在一些变量里;对象行为则通过定义方法来实现。三大基本特征:封装,继承,多态。 ...
  • 使用Java实现面向对象编程

    千次阅读 2018-03-28 11:30:35
    创建类和对象:类属性和行为组成,属性和行为称为类的成员变量.5.类和对象是面向对象的核心概念,类是抽象的,对象是具体的6.类名首字母大写,属性名和方法名采用驼峰命名法,常量名所有字母大写7.构造方法及重载...
  • ”状态的对象行为模式 摘 要   在 理论上,使应用多线程化可以改善性能(通过同时执行多个指令流),并简化程序结构(通过允许每个线程同步地、而不是反应式地或异步地执行)。而在实践中, 由于获取和释放...
  • Java面向对象

    千次阅读 2019-05-08 19:53:54
    封装性:封装是面向对象的核心思想,将对象的属性和行为封装起来,不需要让外界知道具体实现细节。 继承性:继承性主要描述的是类与类之间的关系,通过继承,可以在无需重新编写原有类的情况下,对原有类的功能进行...
  • Java初始化对象的工具 - 构造器

    千次阅读 多人点赞 2020-03-12 02:06:15
    本文关键字:对象、初始化、实例化、构造器、构造方法。明确了类与对象的关系后,我们知道:类只是一个...创建对象的过程叫做类的实例化,或者称为对象的初始化,在这个过程中需要使用的就是new关键字和类的构造器。
  • python类、对象、方法、属性之类与对象

    千次阅读 多人点赞 2016-03-09 10:49:38
    我们通过描述属性(特征)和行为来描述一个对象的。比如家里的小狗,它的颜色,大小,年龄,体重等是它的属性或特征。它会汪汪叫,会摇尾巴等是它的行为。 我们在描述一个真实对象(物体)时包括两个方面: 1.它...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 302,238
精华内容 120,895
关键字:

对象的行为被称为