网站内容策略(现实生活策略模式的定义与特点策略(Strategy)模式分析)
优采云 发布时间: 2021-11-06 12:17网站内容策略(现实生活策略模式的定义与特点策略(Strategy)模式分析)
在现实生活中,我们经常会遇到有多种策略可供选择以实现某个目标的情况。例如,您可以乘飞机旅行、乘坐优采云、骑自行车或开自己的私家车。可以使用超市促销。折扣、免费商品和奖励积分等方法。
类似的情况在软件开发中经常遇到。当有多种算法或策略来实现某个功能时,我们可以根据不同的环境或条件,选择不同的算法或策略来完成该功能,比如数据排序策略中的冒泡。排序、选择排序、插入排序、二叉树排序等。
如果使用多个条件转移语句来实现(即硬编码),不仅条件语句变得非常复杂,而且必须修改原有代码以增加、删除或替换算法,不易维护,违反了开闭原则。如果采用策略模型,这个问题可以很好地解决。
策略模式的定义和特征策略(Strategy)模式的定义:该模式定义了一系列算法,并将每个算法封装起来,可以相互替换,算法的变化不会影响到客户使用算法。策略模式属于对象行为模式。它封装了算法,将使用算法的责任与算法的实现分离,并委托给不同的对象来管理这些算法。
策略模式的主要优点如下。多条条件语句不易维护,使用策略模式可以避免使用多条条件语句,如if...else 语句、switch...case 语句。策略模式提供了一系列可重用的算法系列。正确使用继承可以将算法族的通用代码转移到父类中,避免代码重复。策略模式可以提供相同行为的不同实现方式,客户可以根据不同的时间或空间需求选择不同的实现方式。策略模式对开闭原则提供完美支持,无需修改原有代码即可灵活添加新算法。策略模式将算法的使用放在环境类中,
主要缺点如下。客户必须了解所有策略算法之间的区别,以便在正确的时间选择合适的算法类别。策略模式创建了很多策略类,增加了维护的难度。策略模式的结构和实现 策略模式是准备一组算法,并将这组算法封装成一系列策略类,作为一个抽象策略类的子类。策略模型的重点不是如何实现算法,而是如何组织这些算法,使程序结构更加灵活,具有更好的可维护性和可扩展性。下面我们来分析一下它的基本结构和实现方法。
1.模式结构策略模式的主要作用如下。抽象策略(Strategy)类:定义了一个公共接口,各种算法以不同的方式实现这个接口。环境参与者使用此接口调用不同的算法,一般由接口或抽象类实现。具体策略(Concrete Strategy)类:实现抽象策略定义的接口,并提供具体的算法实现。环境(Context)类:持有一个策略类的引用,最终被客户端调用。
*敏*感*词*如图1所示。
图1 策略模式*敏*感*词*
2.模式实现策略策略模式的实现代码如下:
public class StrategyPattern {
public static void main(String[] args) {
Context c = new Context();
Strategy s = new ConcreteStrategyA();
c.setStrategy(s);
c.strategyMethod();
System.out.println("-----------------");
s = new ConcreteStrategyB();
c.setStrategy(s);
c.strategyMethod();
}
}
//抽象策略类
interface Strategy {
public void strategyMethod(); //策略方法
}
//具体策略类A
class ConcreteStrategyA implements Strategy {
public void strategyMethod() {
System.out.println("具体策略A的策略方法被访问!");
}
}
//具体策略类B
class ConcreteStrategyB implements Strategy {
public void strategyMethod() {
System.out.println("具体策略B的策略方法被访问!");
}
}
//环境类
class Context {
private Strategy strategy;
public Strategy getStrategy() {
return strategy;
}
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
public void strategyMethod() {
strategy.strategyMethod();
}
}
程序的结果如下:
具体策略A的策略方法被访问!
-----------------
具体策略B的策略方法被访问!
策略模式应用实例 【例1】策略模式在“大闸蟹”烹饪中的应用。
分析:大闸蟹的做法很多。我们以清蒸大闸蟹和红烧大闸蟹两种方法为例介绍策略模型的应用。
首先定义一个处理大闸蟹的抽象策略类(CrabCooking),其中收录一个抽象的烹饪方法CookingMethod();然后,为蒸蟹(SteamedCrab)和红烧蟹(BraisedCrab)定义具体的策略类,它们实现了抽象策略类中的抽象方法;因为本程序要显示完成的结果图(点击这里下载要显示的结果图),具体策略类定义为JLabel的子类;最后定义了一个厨房(Kitchen)环境类,它有设置和选择烹饪策略的方法;客户类通过厨房类获取烹饪策略,并以表格形式展示烹饪结果图。图2显示了*敏*感*词*。
图2 大闸蟹烹饪策略*敏*感*词*
程序代码如下:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class CrabCookingStrategy implements ItemListener {
private JFrame f;
private JRadioButton qz, hs;
private JPanel CenterJP, SouthJP;
private Kitchen cf; //厨房
private CrabCooking qzx, hsx; //大闸蟹加工者
CrabCookingStrategy() {
f = new JFrame("策略模式在大闸蟹做菜中的应用");
f.setBounds(100, 100, 500, 400);
f.setVisible(true);
f.setResizable(false);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
SouthJP = new JPanel();
CenterJP = new JPanel();
f.add("South", SouthJP);
f.add("Center", CenterJP);
qz = new JRadioButton("清蒸大闸蟹");
hs = new JRadioButton("红烧大闸蟹");
qz.addItemListener(this);
hs.addItemListener(this);
ButtonGroup group = new ButtonGroup();
group.add(qz);
group.add(hs);
SouthJP.add(qz);
SouthJP.add(hs);
//---------------------------------
cf = new Kitchen(); //厨房
qzx = new SteamedCrabs(); //清蒸大闸蟹类
hsx = new BraisedCrabs(); //红烧大闸蟹类
}
public void itemStateChanged(ItemEvent e) {
JRadioButton jc = (JRadioButton) e.getSource();
if (jc == qz) {
cf.setStrategy(qzx);
cf.CookingMethod(); //清蒸
} else if (jc == hs) {
cf.setStrategy(hsx);
cf.CookingMethod(); //红烧
}
CenterJP.removeAll();
CenterJP.repaint();
CenterJP.add((Component) cf.getStrategy());
f.setVisible(true);
}
public static void main(String[] args) {
new CrabCookingStrategy();
}
}
//抽象策略类:大闸蟹加工类
interface CrabCooking {
public void CookingMethod(); //做菜方法
}
//具体策略类:清蒸大闸蟹
class SteamedCrabs extends JLabel implements CrabCooking {
private static final long serialVersionUID = 1L;
public void CookingMethod() {
this.setIcon(new ImageIcon("src/strategy/SteamedCrabs.jpg"));
this.setHorizontalAlignment(CENTER);
}
}
//具体策略类:红烧大闸蟹
class BraisedCrabs extends JLabel implements CrabCooking {
private static final long serialVersionUID = 1L;
public void CookingMethod() {
this.setIcon(new ImageIcon("src/strategy/BraisedCrabs.jpg"));
this.setHorizontalAlignment(CENTER);
}
}
//环境类:厨房
class Kitchen {
private CrabCooking strategy; //抽象策略
public void setStrategy(CrabCooking strategy) {
this.strategy = strategy;
}
public CrabCooking getStrategy() {
return strategy;
}
public void CookingMethod() {
strategy.CookingMethod(); //做菜
}
}
程序运行结果如图 3 所示。
图3 大闸蟹的烹饪结果
[例2] 策略模型用于实现韶关至婺源的出行方式。
分析:韶关到婺源有几种方式:坐优采云、自驾、自驾。因此,策略模式更适合这个例子。图 4 显示了它的结构。
图4 婺源旅游*敏*感*词*
策略模式的应用场景 策略模式用在很多地方。例如,Java SE 中的容器布局管理就是一个典型的例子。Java SE 中的每个容器都有多种布局供用户选择。在程序设计中,策略模式通常用于以下情况。当系统需要动态选择几种算法中的一种时,可以将每种算法封装成一个策略类。一个类定义了多个行为,这些行为在这个类的操作中以多个条件语句的形式出现。每个条件分支都可以移动到它们各自的策略类中来替换这些条件语句。当系统中的算法完全相互独立时,并且需要对客户隐藏特定算法的实现细节。当系统要求使用算法的客户不应该知道其操作的数据时,可以使用策略模式隐藏与算法相关的数据结构。多个类仅在其性能行为上有所不同。您可以使用策略模式动态选择要在运行时执行的特定行为。策略模式的扩展 在使用策略模式的系统中,当策略很多时,所有策略算法的客户端管理都会变得非常复杂。如果在环境类中使用策略工厂模式来管理这些策略类,会大大减少客户的数量。终端的工作复杂度,其*敏*感*词*如图5所示。当系统要求使用算法的客户不应该知道其操作的数据时,可以使用策略模式隐藏与算法相关的数据结构。多个类仅在其性能行为上有所不同。您可以使用策略模式来动态选择要在运行时执行的特定行为。策略模式的扩展 在使用策略模式的系统中,当策略很多时,所有策略算法的客户端管理都会变得非常复杂。如果在环境类中使用策略工厂模式来管理这些策略类,会大大减少客户的数量。终端的工作复杂度,其*敏*感*词*如图5所示。当系统要求使用算法的客户不应该知道其操作的数据时,可以使用策略模式隐藏与算法相关的数据结构。多个类仅在其性能行为上有所不同。您可以使用策略模式来动态选择要在运行时执行的特定行为。策略模式的扩展 在使用策略模式的系统中,当策略很多时,所有策略算法的客户端管理都会变得非常复杂。如果在环境类中使用策略工厂模式来管理这些策略类,会大大减少客户的数量。终端的工作复杂度,其*敏*感*词*如图5所示。
图5 策略工厂模型*敏*感*词*
进阶阅读如果想了解更多策略模式,可以滑动阅读以下文章。