`
xyheqhd888
  • 浏览: 409232 次
  • 性别: Icon_minigender_1
  • 来自: 秦皇岛
社区版块
存档分类
最新评论

Strategy(策略)模式二

阅读更多

2.重构为Strategy模式:

  上节中给出的getRecommend()方法存在这样几个问题:首先,它太长了,需要我们加注释以解释不同的部分。另外,getRecommend()方法先是选择一个策略,然后执行这个策略;这是两个不同的并且可以分离的功能。我们可使用Stragegy模式来整理这段代码。为了做到这点,需要完成以下几点:

(1)创建一个接口来定义策略操作;

(2)分别在不同的类中以不同的策略来实现这个接口;

(3)重构上一节的代码,选择并使用合适的策略类实例。

假设创建了Advisor接口,如图2所示:


Advisor接口定义多个类可以使用不同策略的操作

 

  Advisor接口说明实现这个接口的类可以接收客户,并推荐焰火制品。重构Customer类中getRecommend()方法代码的下一步是创建表示推荐策略的类。每个类使用不同方式来实现Advisor接口指定的recommend()方法。

 

突破题:如图3所示,推荐逻辑经过重构之后变成了一个策略类的集合。请补充完整该类图。

答:类图如下:


每种策略分别表现为一个公共接口的不同实现


策略类创建之后,接下来的步骤是把代码从Customer类中已有的getRecommend()方法迁移到新的类中。两个最简单的类是GroupAdvisor类和ItemAdvisor类,通过使用现有的推荐引擎来实现接口中的recommend()操作。接口可以只定义实例方法,所以GroupAdvisor类和ItemAdvisor类必须被实例化以支持Advisor接口。然而,只有一个这样的对象是始终有效的,所以在Customer类中为每个实现提供一个单例对象。图4给出了这些类之间的层次关系。



         

 

Advisor接口的实现类依赖于现有的引擎来提供recommend()方法

  Advisor类把对recommend()方法的调用转发给其背后所使用的推荐引擎类。例如,GroupAdvisor类把对recommend()的调用转发给Rel8引擎的advise()方法:

public Firework recommend(Customer c)
{
    return (Firework)Rel8.advise(c);
}

 

突破题:除了Strategy模式之外,请问GroupAdvisor类和ItemAdvisor类还应用了哪些模式?

答:GroupAdvisor和ItemAdvisor类是Adapter模式的实例,提供客户期望的接口,借助于其他不同接口来利用类的服务。

 

 GroupAdvisor和ItemAdvisor类将把对recommend()的调用转发给其背后所使用的推荐引擎类。我们还需要创建PromotionAdvisor类和RandomAdvisor类,通过把当前getRecommended()方法的代码重构到Customer类来实现这一步。与GroupAdvisor和ItemAdvisor类一样,其余类都分别会提供recommend()操作。

 

 在PromotionAdvisor类的构造器中,我们应该判断一下是否有促销活动。另外,还应该在这个类中提供一个hasItem()方法,用它来指示是否有需要促销的焰火制品。

public class PromotionAdvisor implements Advisor
{
	private Firework promoted;

	public PromotionAdvisor(){
		try{
			Properties p = new Properties();
			p.load(ClassLoader.getSystemResourceAsStream("config/strategy.dat"));
			String promotedFireworkName = p.getProperty("promote");
			if(promotedFireworkName != null)
				promoted = Firework.lookup(promotedFireworkName);
		}catch(Exception ignored){
			//Resource not found or failed to load
			promoted = null;
		}
	}

	public boolean hasItem(){
		return promoted != null;
	}

	public Firework recommend(Customer c){
		return promoted;
	}
}

RandomAdvisor类比较简单,具体代码如下:

public class RandomAdvisor implements Advisor
{
	public Firework recommend(Customer c){
		return Firework.getRandom();
	}
}

通过对Customer进行重构,我们实现了对策略选择逻辑(或advisor)和策略使用逻辑的分离。Customer对象的advisor属性保存当前选择的策略。重构后的Customer2类对这个属性进行了滞后初始化,其代码逻辑体现了Oozinoz公司的推销广告策略。

private Advisor getAdvisor(){
	  if(advisor == null) {
		  if(promotionAdvisor.hasItem())
			  advisor = promotionAdvisor;
		  else if(isRegistedred())
			  advisor = gropuAdvisor;
		  else if(isBigSpender())
			  advisor = itemAdvisor;
		  else
			  advisor = randomAdvisor;
	  }
	  return advisor;
}

    

突破题:请写出Customer.getRecommend()方法。

答:

一旦知道了具体的Advisor对象,多态机制就可以完成所有的工作。

 

3.比较Strategy模式和State模式: 

   经重构之后,代码、类以及方法都显得相当简单。这就是这种重构的一个优势,而且重构之后,我们可以更加容易地添加新的策略。这种重构的核心思想就是:将一个操作分布在一组相关的类中。从这点来说,Strategy模式和State模式是一样的。事实上,很多开发人员也不知道这两种策略有什么不同。

  一方面,状态和策略的建模方式存在细微差别。当然,依赖多态性会使得State模式和Strategy模式在结构上看起来几乎相同。

  另一方面,在现实世界中,策略和状态是明显不同的概念。当我们在对状态和策略进行建模的时候,这个实实在在的差异会导致产生完全不同的问题。例如,在对状态进行建模的时候,状态迁移是一个重要方面;而在对策略进行建模的时候,迁移与策略的选择并不相关。另外一个不同之处是,Strategy模式可能允许客户选择或者提供一个策略,而State模式却很少设计这样的思路。

  State模式与Stragety模式的目标存在差异,所以我们继续把它们作为不同的模式。但是应该注意到,并不是每个人都意识到这种差别。

 

4.比较Strategy模式和Template Method模式

   前面曾将排序算法描述为Template Method模式的一个实例。只要一个列表中的对象提供比较两个对象的步骤,那么我们就可以使用Array或者Collection类的sort()算法对这个列表进行排序。但有人可能会争辩说,为一个排序算法提供比较步骤,就是在改变策略。例如,在销售火箭的时候,将火箭按照价格排列和将火箭按照火箭的推进力排列就是两种不同的行销策略。

 

突破题:请问Arrays.sort()方法是Template Method模式的例子,还是Strategy模式的例子?请给出理由。

答:认为该排序算法是Strategy模式的范例的观点是:Template Method模式可以让子类重新定义算法的某些具体步骤。但是,Collections.sort()方法并没有使用子类;该方法需要使用一个Comparator实例。每个Comparator实例都提供一个新方法,因此,也提供一个新的算法和一个新的策略。因而sort()方法是Strategy模式的一个很好的范例。

    认为该排序算法是Template Method模式的范例的观点是:排序算法有很多,但是Collections.sort()方法仅使用了一种排序算法(Quicksort)。改变算法意味着要把算法变为堆排序或者冒泡排序。Strategy模式的目的在于方便我们使用不同的算法。但是现在却不行。Template Method模式的目的在于方便我们在某个算法中插入一个特定步骤。这正是sort()方法的工作机制。

 

5.小结

  对不同策略建模的逻辑可能只出现在一个类中,并且常常只出现在一个方法中。这样的方法可能会变得过于复杂,并且可能将策略选择与策略执行混在了一起。

  为了简化这样的代码,我们可以创建一组类,并用每个类来表示不同的策略。具体而言,我们可以在这些类中定义一个相同的操作,并在每个类对这个操作的实现中封装一种策略。另外,我们还需要为用户提供策略选择逻辑。这种策略选择代码逻辑,即使是在重构后仍然可能比较复杂;但是,我们应该能够简化它,使之接近于问题域中描述策略选择的伪代码。

  在典型情况下,客户将使用一个上下文变量来保存选择的策略,借助多态性来执行合适的策略,从而使得策略的执行变得非常地简单,客户在收到策略操作调用请求之后只需将该请求转发给上下文变量即可。通过将可选的策略封装在单独的类中,并让每个类都实现一个共同的操作,我们可通过Strategy模式创建一系列整洁而又简单的代码,以此来完成对各种解决问题的方案的建模。

  • 大小: 1.3 KB
  • 大小: 6.7 KB
  • 大小: 5.2 KB
分享到:
评论

相关推荐

    (行为型模式) Strategy 策略模式

    C#面向对象设计模式 (行为型模式) Strategy 策略模式 视频讲座下载

    strategy策略模式源码

    策略模式是一种行为设计模式,它使你能在运行时改变对象的行为。...在提供的压缩包文件"strategy"中,可能包含了关于策略模式的示例代码或者详细解释,你可以解压后查看,进一步理解和学习策略模式的实现和应用。

    策略(strategy)模式

    2. **封装变化**:策略模式封装了变化的算法,使得客户端代码无需关心具体算法的实现,只与策略接口交互,降低了系统的耦合度。 3. **多态性**:所有策略类都实现了同一个接口,因此可以在运行时以多态方式选择并...

    C#面向对象设计模式纵横谈(23):(行为型模式) Strategy 策略模式

    策略模式的核心组成部分包括上下文(Context)、策略(Strategy)和具体策略(Concrete Strategy)。上下文是使用策略的对象,它定义了客户所期望的接口,并负责调用具体策略对象的算法。策略是所有具体策略的抽象接口,它...

    设计模式C++学习之策略模式(Strategy)

    在`Demo1_Strategy`这个示例中,可能包含了多个C++源文件,分别实现了策略模式的不同方面,例如定义了策略接口、具体策略类以及上下文类的实现。通过分析这些源代码,我们可以更深入地理解策略模式的用法和优势。 ...

    走进设计模式之 策略模式(Strategy)

    策略模式是一种行为设计模式,它使你能在运行时改变对象的行为。在软件设计中,有时我们需要根据不同的场景或条件选择不同的算法或行为。策略模式允许我们将这些算法封装成独立的类,每个类代表一种策略,然后在运行...

    C#面向对象设计模式纵横谈\23 行为型模式Strategy策略模式.zip

    在这里与各位分享本人从网络上下载的C#面向对象设计模式纵横谈系列视频,共有25节,除了第一节需要各位贡献一点资源分以作为对本人上传资源的回馈,后面的其他资源均不需要... 这是第23节:行为型模式Strategy策略模式

    设计模式之策略模式(Strategy Pattern)

    在策略模式中,有三个主要角色:策略接口(Strategy Interface)、具体策略类(Concrete Strategy Classes)和上下文(Context)。策略接口定义了所有支持的算法的公共接口,这样上下文就可以通过这个接口来调用这些...

    策略模式(strategy)

    策略模式的核心组成部分包括策略(Strategy)、上下文(Context)和具体策略(Concrete Strategies)。策略定义了算法家族,而上下文则使用这些策略,但并不知道具体的实现细节。具体策略是实现了策略接口的具体算法...

    【Java设计模式】(2)策略模式Strategy

    策略模式(Strategy)是软件设计模式中的一种行为模式,它使你能在运行时改变对象的行为。在Java中,策略模式通常涉及定义一系列算法,并将每个算法封装起来,使得它们可以相互替换,同时使得算法的变化独立于使用它...

    策略模式 Strategy Pattern

    ### 策略模式 Strategy Pattern #### 概述 策略模式是一种行为设计模式,它使得算法可以在运行时被更改。这种模式允许一个类的行为或其算法在运行时根据需要进行改变,通过这种方式,我们可以轻松地扩展不同的算法...

    详解SpringBoot结合策略模式实战套路

    SpringBoot结合策略模式实战套路 策略模式是一种常用的设计模式,它可以使我们的代码更加灵活、可维护和可扩展。在SpringBoot项目中,策略模式可以与依赖注入机制相结合,实现更加灵活的业务逻辑处理。在本文中,...

    行为型——Strategy(策略模式)

    策略模式的核心组成部分包括环境(Context)、策略(Strategy)和具体策略(Concrete Strategy)。 1. **环境(Context)**:这是使用策略的对象,它维持一个对策略对象的引用,可以在运行时根据需要选择合适的策略。环境...

    设计模式之策略模式(Strategy Pattern)

    策略模式的主要组成部分包括上下文(Context)、策略接口(Strategy Interface)和具体策略类(Concrete Strategy Classes)。上下文维护一个对策略对象的引用,并使用这个引用来调用策略对象的算法。策略接口定义了...

    Java 设计模式-策略模式(Strategy)Android讲解

    首先,策略模式由三个主要组成部分构成:上下文(Context)、策略(Strategy)接口和具体策略(Concrete Strategy)。上下文是使用策略的对象,它维护一个对策略的引用,并调用策略的接口来执行算法。策略接口定义了一组...

    [行为模式] head first 设计模式之策略模式(strategy)

    2. **可扩展性**:策略模式使得系统易于扩展新的算法,因为策略类和客户端代码是解耦的。 在策略模式中,通常有三个主要角色: - **策略接口(Strategy Interface)**:定义了所有支持的算法的公共接口,这样任何...

    设计模式-策略模式(Strategy)

    策略模式是一种行为设计模式,它使你能在运行时改变对象的行为。这种模式允许你使用算法族,而无需在代码中硬编码这些算法。通过将算法封装到具有共同接口的独立对象中,策略模式使得你可以根据需要灵活地切换算法,...

    strategy(策略模式Java代码实现).rar

    这个"strategy(策略模式Java代码实现).rar"压缩包很可能包含了展示如何在实际项目中运用策略模式的代码示例。 策略模式的核心概念是定义一系列算法,并将每一个算法封装起来,使它们可以相互替换。这些算法都属于同...

    策略模式在实际项目中的应用二

    例如,"策略模式在实际项目中的应用二"可能涉及到一个系统中对不同数据处理策略的灵活切换。在这个测试Demo中,我们可能有一个核心业务逻辑,它需要根据不同的条件或请求,采用不同的策略进行处理。这些策略可以是...

    桥接模式和策略模式的区别,内含可运行代码和两者详细区别

    而策略模式(Strategy Pattern)则是定义一系列的算法,并将每一个算法封装起来,使它们可以相互替换。策略模式让算法的变化独立于使用它的客户端。它主要用于处理那些具有多种行为的对象,可以根据具体情境选择不同...

Global site tag (gtag.js) - Google Analytics