Gof23种设计模式(22)——策略模式(Strategy)

2020年8月14日10:25:29 评论 74

1 基础知识

1.1 标准定义

策略模式标准定义:定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。

1.2 分析和说明

策略(Strategy)模式属于对象的行为模式,通过分析Strategy模式可以发现:策略模式针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。策略模式把行为和环境分开。环境类负责维持和查询行为类,各种算法在具体的策略类中提供。由于算法和环境独立开来,算法的增减,修改都不会影响到环境和客户端。

在软件设计中,经常会遇到因为一开始考虑不够长远而导致后面遇到很大的麻烦。开发者只是想尽快地解决问题而没考虑到后期的维护或者根本没法预料到将来会有什么样的变化干脆置之不理。针对这个问题,Strategy模式提供了一个解决问题的方案:面向接口编程而不是实现,发现其中会改变的部分作为扩展点,然后把它封装起来。

Strategy结构如图1所示,其角色包括环境(Context)角色、抽象策略(Strategy)角色和具体策略(Concrete Strategy)角色。

Gof23种设计模式(22)——策略模式(Strategy)图1 策略模式结构

环境(Context)角色:拥有一个Strategy接口的引用。环境(Context)角色可以是接口、具体类或抽象类。该角色不可缺少。

抽象策略(Strategy)角色:这是一个抽象角色,此角色给出所有的具体策略类所需的统一接口,或者是定义所有支持的算法的公共接口。通常由一个接口或抽象类实现。

具体策略(Concrete Strategy)角色:包装了相关的算法或行为。具体策略(Concrete Strategy)角色都是由具体类来实现。以Strategy接口实现某具体算法。

当客户调用Context时,它将客户的请求转发给它的Strategy。Context将该算法所需的所有数据传递给Strategy,或者将自身作为参数传递给Strategy,使Strategy可以回调Context。ConcreteStrategy实现具体算法。

2 应用场景举例

比如公司在多个行业中有项目,对于不同的行业,项目有不同的做法。行业项目就是环境(Context)角色。有一个抽象策略(Strategy)角色。而银行行业项目管理策略、能源行业项目管理策略、电信行业项目管理策略、政府项目管理策略全部都继承抽象策略并有各个行业的实现模式。用例如图2所示。

Gof23种设计模式(22)——策略模式(Strategy)图2 策略模式用例图

在这里可以把Project类理解为环境(Context)角色。Strategy抽象类是抽象策略(Strategy)角色。BankStrategy类、GovernmentStrategy类、TelecomStrategy类是具体策略(Concrete Strategy)角色。其实现类图如图3所示。BankStrategy类、GovernmentStrategy类和TelecomStrategy类继承Strategy抽象类,Project类关联Strategy抽象类。

Gof23种设计模式(22)——策略模式(Strategy)图3 策略模式类图

策略模式实现顺序图见图4,实现顺序描述:
①基于Project类创建一个projectA对象;
②基于BankStrategy类创建一个strategy1对象;
③基于GovernmentStrategy类创建一个strategy2对象;
④基于TelecomStrategy类创建一个strategy3对象;
⑤调用projectA对象的setStrategy方法,把strategy1对象赋值给projectA对象;
⑥调用projectA对象的doStrategyWork,显示当前projectA对象的策略工作;
⑦-⑧与⑤-⑥基本相同,不过给projectA对象赋值为strategy2对象,并显示projectA对象在strategy2下的策略工作;
⑨-⑩与⑤-⑥基本相同,不过给projectA对象赋值为strategy3对象,并显示projectA对象在strategy3下的策略工作。

Gof23种设计模式(22)——策略模式(Strategy)图4 策略模式实现顺序图

当客户需要调用project的策略活动时,将不同的Strategy传递给project,这些策略包括银行(BankStrategy)策略、政府(GovernmentStrategy)策略和电信(TelecomStrategy)策略。当调用project的具体策略工作时,实际上由这些不同策略来完成工作。

3.Java的实现程序代码

Java程序实现主要包括Project类文件,Strategy抽象类文件,BankStrategy类文件、GovernmentStrategy类文件和TelecomStrategy类文件等5个文件。其关系如图3所示。下面分别列出这5个文件的程序代码,最后列出测试代码并显示输出结果。

Project类程序代码清单01所示。

程序代码清单01

public class Project {

	private String projectName;
	private Strategy strategy;

	public Project(String projectName) {
		super();
		this.projectName = projectName;
	}

	public Project(String projectName, Strategy strategy) {
		super();
		this.projectName = projectName;
		this.strategy = strategy;
	}

	public String getProjectName() {
		return projectName;
	}

	public void setProjectName(String projectName) {
		this.projectName = projectName;
	}

	public Strategy getStrategy() {
		return strategy;
	}

	public void setStrategy(Strategy strategy) {
		this.strategy = strategy;
	}

	public void doCommonWork() {
	}

	public void doStrategyWork() {
		strategy.doWork(this);
	}
}

Strategy抽象类程序代码清单02所示。

程序代码清单02

public abstract class Strategy {

	public void doWork(Project project) {
	}

}

BankStrategy类、GovernmentStrategy类、TelecomStrategy类继承Strategy抽象类,其程序代码清单03所示。

程序代码清单03

public class BankStrategy extends Strategy {

	public void doWork(Project project) {
		System.out.println(project.getProjectName() + "采用银行策略的工作。");
	}
}

public class GovernmentStrategy extends Strategy {

	public void doWork(Project project) {
		System.out.println(project.getProjectName() + "采用政府策略的工作");
	}
}

public class TelecomStrategy extends Strategy {

	public void doWork(Project project) {
		System.out.println(project.getProjectName() + "采用电信策略的工作");
	}
}

策略模式测试程序的代码清单04如下:

程序代码清单04

public class Client {

	public static void main(String[] args) {

		System.out.println("——————要求projectA采用银行策略——————");
		Project projectA = new Project("projectA");
		Strategy strategy1 = new BankStrategy();

		projectA.setStrategy(strategy1);
		projectA.doStrategyWork();

		System.out.println("——————要求projectB采用政府策略——————");

		Project projectB = new Project("projectB");
		Strategy strategy2 = new GovernmentStrategy();

		projectB.setStrategy(strategy2);
		projectB.doStrategyWork();

		System.out.println("——————要求projectC采用电信策略——————");

		Project projectC = new Project("projectC");
		Strategy strategy3 = new TelecomStrategy();

		projectC.setStrategy(strategy3);
		projectC.doStrategyWork();
	}
}

策略模式测试类输出结果如下所示:

——————要求projectA采用银行策略——————
projectA采用银行策略的工作。
——————要求projectB采用政府策略——————
projectB采用政府策略的工作
——————要求projectC采用电信策略——————
projectC采用电信策略的工作

参考链接

11种行为型模式

Gof23种设计模式(13)——解释器模式(Interpreter)
Gof23种设计模式(14)——模板方法模式(Template Method)
Gof23种设计模式(15)——责任链模式(Chain of Responsibility)
Gof23种设计模式(16)——命令模式(Command)
Gof23种设计模式(17)——迭代器模式(Iterator)
Gof23种设计模式(18)——中介者模式(Mediator)
Gof23种设计模式(19)——备忘录模式(Memento)
Gof23种设计模式(20)——观察者模式(Observer)
Gof23种设计模式(21)——状态模式(State)
Gof23种设计模式(22)——策略模式(Strategy)
Gof23种设计模式(23)——访问者模式(Visitor)
Gof23种设计模式 —— 行为型模式总结和比较

回到总目录Gof23种设计模式(全解析)

(转载自微信公众号:架构设计模式)

素课网
  • 本文由 发表于 2020年8月14日10:25:29
  • 转载请注明:https://www.suketech.com/9286.html
设计模式:面向对象设计的六大原则 - 总结 设计模式

设计模式:面向对象设计的六大原则 – 总结

开闭原则是面向对象设计中最基础的设计原则,它指导我们如何建立稳定灵活的系统。开闭原则可能是设计模式六项原则中定义最模糊的一个了,它只告诉我们对扩展开放,对修改关闭,可是到底如何才能做到对扩展开放,对修...
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: