java设计模式之策略模式

1,什么是策略模式?

策略模式,又叫算法簇模式,就是定义了不同的算法族,并且之间可以互相替换,此模式让算法的变化独立于使用算法的客户。

2,策略模式有什么好处?

     策略模式的好处在于你可以动态的改变对象的行为。 

3,设计原则  

     设计原则是把一个类中经常改变或者将来可能改变的部分提取出来,作为一个接口(c++z中可以用虚类),然后在类中包含这个对象的实例,这样类的实例在运行时就可以随意调用实现了这个接口的类的行为。下面是一个例子。 

      策略模式属于对象行为型模式,主要针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响 到客户端的情况下发生变化。通常,策略模式适用于当一个应用程序需要实现一种特定的服务或者功能,而且该程序有多种实现方式时使用。

4 ,策略模式中有三个对象:
(1)环境对象:该类中实现了对抽象策略中定义的接口或者抽象类的引用。
(2)抽象策略对象:它可由接口或抽象类来实现。
(3)具体策略对象:它封装了实现同功能的不同算法。
       利用策略模式构建应用程序,可以根据用户配置等内容,选择不同有算法来实现应用程序的功能。具体的选择有环境对象来完成。采用这种方式可以避免由于使用条件语句而带来的代码混乱,提高应用程序的灵活性与条理性。

        在我们平时做开发的时候吧,不同的问题有不同的算法来实现。加入有如下问题:有5个小朋友,每个小朋友有5个苹果,计算一下,总共有几个苹果呢?于是,A同学看到之后,很简单啊,这样就ok了:

public class Calculate {
	
	public int calculate(){
		int sum = 5+5+5+5+5;
		return sum;
	}
}

为此,A同学还写好了测试代码,如下:

public class StrategyTest {
	
	public static void main(String[] args) {
			Calculate calculate = new Calculate();
			System.out.print("apple sum = "+calculate.calculate());
	}
}
运行结果是:apple sum = 25,嗯,不错,答案显然是正确的。但此时呢,B同学又说了,我也有一种方法来实现它,在你的基础上改一下就好了,如下:

public class Calculate {
	
	public int calculate(int method){
		int sum = 0;
		switch (method) {
		case 1:
			sum = 5+5+5+5+5;
			break;
		case 2:
			sum = 5 *5;
			break;
		}
		return sum;
	}
}
运行结果与A同学的方法一致,看来方法也是可行的。但是正所谓,1000个人读哈姆雷特就有1000中体会感受,所以对同一个问题会有不同的算法来能实现,那按上面的写法的话,会使得代码的可读性以及维护拓展降低。所以,遇到这种情况怎么办呢?对,你想到了,策略,把方法都提取出来,形成策略。

首先,定义一个策略接口:

public interface IStrategy {
	int calculate();
}
然后呢,定义2个子类都实现上述的接口,并加入不同的算法

public class Straegy1 implements IStrategy{

	@Override
	public int calculate() {
		return (5+5+5+5+5);
	}

}
public class Straegy2 implements IStrategy{

	@Override
	public int calculate() {
		return (5*5);
	}

}
那么环境角色呢,就是上面的Calculate这个类咯,我们只要稍微的改动一下就可以了,如下:

public class Calculate {
	
	private IStrategy strategy;
	
	public Calculate(IStrategy strategy) {
		this.strategy = strategy;
	}

	public int calculate(){
		return strategy.calculate();
	}
}
好了,写完了,感觉自己是不是特别棒呢,下面我们就测试一下,到底结果如何呢?测试代码如下:

public class StrategyTest {
	
	public static void main(String[] args) {
		
			Calculate calculate1 = new Calculate(new Straegy1());
			System.out.println("Straegy1:apple sum = "+calculate1.calculate());
			
			Calculate calculate2 = new Calculate(new Straegy2());
			System.out.println("Straegy2:apple sum = "+calculate2.calculate());
	}
}
测试结果如下:
Straegy1:apple sum = 25
Straegy2:apple sum = 25

嗯,不错,运行的结果是一致的,看来我们的策略ok了。接下来,有的人会发现,环境角色Calculate完全没必要存在嘛,让系统根据不同的场景执行不同的侧率不就完事了嘛,执行以下代码也是可以的:

public class StrategyTest {
	
	public static void main(String[] args) {
		
			Straegy1 straegy1 = new Straegy1();
			System.out.println("Straegy1:apple sum = "+straegy1.calculate());
			
			Straegy2 straegy2 = new Straegy2();
			System.out.println("Straegy2:apple sum = "+straegy2.calculate());
	}
}
运行结果也是一致的:

Straegy1:apple sum = 25
Straegy2:apple sum = 25

嗯,好像是那么一回事哦。但是仔细的再想想,考虑一下我说的以下几种情况:

1.如果我们在不同的策略中需要初始化一些相同的数据,该怎么办呢?如果我们没有环境角色这个中间体的存在,那我们势必会在方法体里面初始化,但如果我们有了这个中间环境角色,那我们完全可以在环境变量的构造函数中来实现初始化了,这样我们就减少了代码的冗余。

2.如果我们需要改变原有的算法,引进新的参数的时候怎么办呢?一种是重载该算法,增加新的函数接口,另一种是完全废弃掉当前函数接口,重写全新的函数接口。很显然啊,这两种方式的代价都是不可估量的,尤其是只有部分策略需要用到的时候。因此啊,我们用环建角色这个中间体就可以轻松的搞定了。

下面就是我改造的那个策略模式接口,让我们的策略模式也持有环境角色这一变量,这样在不同的策略中,就都可以回调环境角色中的所有的可用函数和变量了。如下:

public interface IStrategy {
	int calculate(Calculate calculate);
}
public class Straegy1 implements IStrategy{

	@Override
	public int calculate(Calculate calculate) {
		return (5+5+5+5+5);
	}

}
public class Straegy2 implements IStrategy{

	@Override
	public int calculate(Calculate calculate) {
		return (5*5);
	}

}
好了,现在需求稍微有点变动,我们需要在Straegy2中知道,这种策略是谁提供的,用author表示。加入没有环境角色的存在,大家应该会去接口和实现接口类中去修改咯,但是,Straegy1的提供者就不乐意了,因为你改动的话他也需要做相应的改动。有了环境角色之后,这一切看起来就都不那么麻烦了,你也不需要去改动策略接口和实现策略接口类Straegy2,只需要改动一下环境角色类Calculate和策略Straegy2就可以了,如下:

public class Calculate {
	
	private IStrategy strategy;
	private String author;
	
	public Calculate(IStrategy strategy) {
		this.strategy = strategy;
	}

	public Calculate(IStrategy strategy,String author) {
		this.strategy = strategy;
		this.author = author;
	}
	
	public int calculate(){
		return strategy.calculate(this);
	}

	public String getAuthor() {
		return author;
	}
	
}
public class Straegy2 implements IStrategy{

	@Override
	public int calculate(Calculate calculate) {
		System.out.println("Straegy2 author is "+calculate.getAuthor());
		return (5*5);
	}

}
测试代码如下:

public class StrategyTest {
	
	public static void main(String[] args) {
		
			Calculate calculate1 = new Calculate(new Straegy1());
			System.out.println("Straegy1:apple sum = "+calculate1.calculate());
			
			Calculate calculate2 = new Calculate(new Straegy2(),"dandy");
			System.out.println("Straegy2:apple sum = "+calculate2.calculate());
	}
}

测试结果如下:

Straegy1:apple sum = 25
Straegy2 author is dandy
Straegy2:apple sum = 25

 由以上分析可见,策略模式中,各个角色的功能都非常重要,虽然环境角色可以在某些简单的策略模式中不去使用,但是如果无法预测到各个实现策略功能和需求的变化,以及实现灵活性更好的策略模式,在使用策略模式进行架构时,一定要充分利用所有角色的功能


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值