战略模式的真实例子


95

我一直在阅读有关OCP主体以及如何使用策略模式来实现此目的的信息。

我打算尝试向几个人解释这一点,但是我能想到的唯一示例是根据“订单”的状态使用不同的验证类。

我已经在线阅读了几篇文章,但这些文章通常不会描述使用该策略的真实原因,例如生成报告/账单/验证等。

您是否认为现实世界中有常见的策略模式示例?

Answers:


100

那这个呢:

您必须加密文件。

对于小文件,可以使用“内存中”策略,其中读取完整的文件并将其保存在内存中(例如,文件<1 gb)

对于大文件,可以使用另一种策略,其中部分文件在内存中读取,部分加密结果存储在tmp文件中。

对于同一任务,这可能是两种不同的策略。

客户端代码看起来相同:

 File file = getFile();
 Cipher c = CipherFactory.getCipher( file.size() );
 c.performAction();



// implementations:
interface  Cipher  {
     public void performAction();
}

class InMemoryCipherStrategy implements Cipher { 
         public void performAction() {
             // load in byte[] ....
         }
}

class SwaptToDiskCipher implements Cipher { 
         public void performAction() {
             // swapt partial results to file.
         }

}

     Cipher c = CipherFactory.getCipher( file.size() );

将为密码返回正确的策略实例。

我希望这有帮助。

(我什至不知道密码是否是正确的词:P)


8
您的示例不再是工厂模式吗?我也认为它例如在C#中不起作用。您的“ getCipher()”方法是静态方法,但是在C#中,您不能在接口上定义静态方法(我认为既不是Java,但是对此我不确定)。
FrenchData

10
他们一起去。工厂创建策略,但是该策略自行持有算法以执行(基本上)相同的操作。也可以在运行时更改策略。关于您正确的工厂方法,我已经对其进行了更改。
OscarRyz 2010年

要在没有工厂的情况下添加Osacars点,可以在没有工厂的情况下创建 Cipher C =null; if (file.size() <= 2048) { C = new InMemoryCipherStrategy(); } else { c= SwaptToDiskCipher (); }
Abhijit Mazumder 2014年

同意@FrenchData。虽然这是一个很好的例子,但CipherFactory可能会使那些不熟悉策略模式的人感到困惑。
user487772 2015年

1
工厂模式与创造有关,策略与行为有关。还有一点不同的权利吗?
nhoxbypass

62

再次,一个旧的帖子,但仍然出现在搜索上,因此我将再添加两个示例(代码在C#中)。我绝对喜欢Strategy模式,因为它节省了很多时间,项目经理说:“我们希望应用程序执行'X',但是'X'尚不明确,并且在不久的将来可能会发生变化。 ” 该视频介绍了策略模式,以StarCraft为例。

属于此类别的东西:

  • 排序:我们想对这些数字进行排序,但是我们不知道是否要使用BrickSort,BubbleSort或其他排序方式

  • 验证:我们需要根据“某些规则”检查项目,但尚不清楚该规则将是什么,我们可能会想到新的规则。

  • 游戏:我们希望玩家移动时走路或跑步,但也许将来,他也应该能够游泳,飞行,传送,地下挖洞等。

  • 存储信息:我们希望应用程序将信息存储到数据库,但是稍后可能需要能够保存文件或进行网络通话

  • 输出:我们需要将X输出为纯字符串,但稍后可能是CSV,XML,JSON等。


例子

我有一个项目,用户可以在其中将产品分配给数据库中的人员。将产品分配给个人的状态为“已批准”或“已拒绝”,这取决于某些业务规则。例如:如果用户将产品分配给一定年龄的人,则其状态应被拒绝;如果项目中两个字段之间的差异大于50,则其状态会下降,依此类推。

现在,在开发之时,这些业务规则尚未完全清楚,并且随时可能出现新的规则。策略模式的功能是我创建了RuleAgent,并为其提供了IRule列表。

public interface IRule {
    bool IsApproved(Assignment assignment); 
 }

在将产品分配给人员时,我创建了RuleAgent,为其提供了规则列表(所有规则均实现IRule),并要求其验证分配。它会遵循所有规则。由于它们都实现相同的接口,因此它们都具有IsApproved方法,并且如果其中任何一个返回false,则返回false。

现在,例如,当经理突然出现并说,我们还需要拒绝对实习生的所有分配,或对加班的人的所有分配……您制作了新的此类:

public OvertimeRule : IRule
{
    public bool IsApproved(Assignment assignment) //Interface method
    {
        if (assignment.Person.Timesheet >= 40)
        {
            return false;
        }
        return true;
    }
}

public InternRule : IRule
{
    public bool IsApproved(Assignment assignment) //Interface method
    {
        if (assignment.Person.Title == "Intern")
        {
            return false;
        }
        return true;
    }
}

您会看到不必不必继续添加或删除if语句或代码,只需创建一个新的规则类即可实现IRUle接口,并在需要时将其切换出去。


另一个很好的例子:Scott Allen在http://www.asp.net/mvc/pluralsight上的视频系列,其中他在应用程序的单元测试部分中使用了策略模式。

他建立了一个网站,该网站的页面根据受欢迎程度显示商品。但是,“热门”可以是很多东西(大多数视图,大多数订户,创建日期,大多数活动,最少评论等),并且如果管理层尚不知道确切的订购方式,并且可能想尝试不同的方法以后订购。您可以使用order方法创建一个接口(IOrderAlgorithm或其他东西),然后让Orderer对象将订购委托给IOrderAlgorithm接口的具体实现。您可以创建一个“ CommentOrderer”,“ ActivityOrderer”等...,并在出现新需求时将其切换出来。


我知道这超出了问题的范围,但是接下来会发生什么呢?我们InternRule现在有了这个,但如何触发OvertimeRule呢?我们如何确保OvertimeRule.IsApproved现在调用的任何逻辑也调用InternRule.IsApproved
Spencer Ruport

14

重要说明:

  1. 策略是行为设计​​模式。它用于在一系列算法之间切换。

  2. 该模式包含一个抽象策略接口以及该接口的许多具体策略实现(算法)。

  3. 该应用程序仅使用策略界面。根据某些配置参数,具体策略将被标记为interface

维基百科的 UML图

在此处输入图片说明

一个真实的例子:航空公司在某些月份(7月至12月)提供折扣。你可以有一个票价模块,该模块根据月数决定定价选项。

看一个简单的例子。该示例可以扩展到在线零售应用程序,该应用程序可以在特殊的日子/欢乐时光轻松为购物车商品提供折扣。

import java.util.*;

/* Interface for Strategy */
interface OfferStrategy {
    public String getName();
    public double getDiscountPercentage();
}
/* Concrete implementation of base Strategy */
class NoDiscountStrategy implements OfferStrategy{
    public String getName(){
        return this.getClass().getName();
    }
    public double getDiscountPercentage(){
        return 0;
    }
}
/* Concrete implementation of base Strategy */
class QuarterDiscountStrategy implements OfferStrategy{
    public String getName(){
        return this.getClass().getName();
    }
    public double getDiscountPercentage(){
        return 0.25;
    }
}
/* Context is optional. But if it is present, it acts as single point of contact
   for client. 

   Multiple uses of Context
   1. It can populate data to execute an operation of strategy
   2. It can take independent decision on Strategy creation. 
   3. In absence of Context, client should be aware of concrete strategies. Context acts a wrapper and hides internals
   4. Code re-factoring will become easy
*/
class StrategyContext {
    double price; // price for some item or air ticket etc.
    Map<String,OfferStrategy> strategyContext = new HashMap<String,OfferStrategy>();
    StrategyContext(double price){
        this.price= price;
        strategyContext.put(NoDiscountStrategy.class.getName(),new NoDiscountStrategy());
        strategyContext.put(QuarterDiscountStrategy.class.getName(),new QuarterDiscountStrategy());        
    }
    public void applyStrategy(OfferStrategy strategy){
        /* 
        Currently applyStrategy has simple implementation. You can use Context for populating some more information,
        which is required to call a particular operation            
        */
        System.out.println("Price before offer :"+price);
        double finalPrice = price - (price*strategy.getDiscountPercentage());
        System.out.println("Price after offer:"+finalPrice);
    }
    public OfferStrategy getStrategy(int monthNo){
        /*
            In absence of this Context method, client has to import relevant concrete Strategies everywhere.
            Context acts as single point of contact for the Client to get relevant Strategy
        */
        if ( monthNo < 6 )  {
            return strategyContext.get(NoDiscountStrategy.class.getName());
        }else{
            return strategyContext.get(QuarterDiscountStrategy.class.getName());
        }

    }
}
public class StrategyDemo{    
    public static void main(String args[]){
        StrategyContext context = new StrategyContext(100);
        System.out.println("Enter month number between 1 and 12");
        int month = Integer.parseInt(args[0]);
        System.out.println("Month ="+month);
        OfferStrategy strategy = context.getStrategy(month);
        context.applyStrategy(strategy);
    }

}

输出:

Enter month number between 1 and 12
Month =1
Price before offer :100.0
Price after offer:100.0

Enter month number between 1 and 12
Month =7
Price before offer :100.0
Price after offer:75.0

有用的文章:

战略dzone的模式

来源决策的战略模式


谢谢...。使之具有合理的意义。...同意的applyStrategy()是实现大量黑魔法的怪物。在strategyContext中持有策略的非静态方法也是一流的
Arnab Dutta

12

我可以想到几个非常简单的示例:

  • 排序列表。该策略是用于确定列表中两个项目中的哪一个是“第一”的比较
  • 您可能有一个应用程序,可以在运行时选择排序算法本身(QuickSort,HeapSort等)
  • Log4NetLog4j中的 Appender,布局和过滤器
  • UI工具箱中的布局管理器
  • 数据压缩。您可能有一个ICompressor接口,其唯一方法如下所示:

    byte [] compress(byte [] input);

    您的具体压缩类可能是RunLengthCompression,DeflateCompression等。


9

策略模式的一种常见用法是定义自定义排序策略(使用不具有高阶函数的语言),例如,在Java中按长度对字符串列表进行排序,并传递一个匿名内部类(策略接口的实现):

List<String> names = Arrays.asList("Anne", "Joe", "Harry");
Collections.sort(names, new Comparator<String>() {
  public int compare(String o1, String o2) {
    return o1.length() - o2.length();
  }
});
Assert.assertEquals(Arrays.asList("Joe", "Anne", "Harry"), names);

以类似的方式,策略可以用于对象数据库的本地查询,例如在db4o中:

List<Document> set = db.query(new Predicate<Document>() {
  public boolean match(Document candidate) {
    return candidate.getSource().contains(source);
  }
});

8

我有一个应用程序,可以每天根据我们的企业目录同步其用户群。用户的资格取决于他们在大学中的身份。每天,供应程序都会进行审核,并确保在应用程序中供应了那些符合条件的用户,而没有取消配置的用户(实际上是根据正常的降级算法进行的,但这不重要)。在星期六,我将进行更彻底的更新,以同步每个用户的某些属性,并确保他们具有适当的资格。在月底,我会根据该月的使用情况进行一些账单处理。

我使用可组合策略模式来执行此同步。主程序基本上根据星期几(仅同步更改/全部同步)和相对于学术日历的学期时间选择主策略。如果计费周期即将结束,则它还将与计费策略结合在一起。然后,它通过标准界面运行所选策略。

我不知道这有多普遍,但我觉得它非常适合该策略模式。


这是一个很好的例子。另外,它清楚地告诉您命令和策略模式之间的区别-目的。“主程序基本上根据星期几选择主策略”
Utsav T

7

我知道这是一个古老的问题,但是我想我还有一个最近实现的有趣的例子。

这是在文档传递系统中使用的策略模式的非常实际的示例。

我有一个PDF传送系统,该系统接收了包含大量文档和一些元数据的档案。根据元数据,它决定将文档放在何处;比如,根据数据,我可以存储在文件中ABC存储系统,或三者的组合。

不同的客户使用此系统,并且在出现错误的情况下对回滚/错误处理的要求也不同:一个人希望传递系统在出现第一个错误时停止,将所有已经传递的文档保留在他们的存储中,但是停止该过程,而不传递其他任何东西; 另一个人希望它B在存储时发生错误的情况下进行回滚C,但保留已经交付的内容A。不难想象,第三或第四个人也会有不同的需求。

为了解决该问题,我创建了一个基本的交付类,其中包含交付逻辑以及用于从所有存储中回滚东西的方法。如果发生错误,交付系统实际上不会直接调用这些方法。相反,该类使用“依赖注入”来接收“回滚/错误处理策略”类(基于使用系统的客户),以防发生错误时调用该类,如果适用于该策略,则依次调用回滚方法。

交付类本身报告策略类正在发生的情况(将什么文档交付给什么存储,以及发生了什么故障),并且每当发生错误时,它都会询问策略是否继续。如果该策略说“停止它”,则该类将调用该策略的“ cleanUp”方法,该方法使用先前报告的信息来确定要从交付类中调用哪些回滚方法,或者什么都不做。

rollbackStrategy.reportSuccessA(...);
rollbackStrategy.reportFailureB(...);

if (rollbackStrategy.mustAbort()) {
    rollbackStrategy.rollback(); // rollback whatever is needed based on reports
    return false;
}

因此,我现在有两种不同的策略:一种是QuitterStrategy(在出现第一个错误时退出并不清除任何内容),另一种是MaximizeDeliveryToAStrategy(尝试尽可能不中止该进程并且从不回退交付给存储的内容A,但是从B交付C失败到失败。

据我了解,这是策略模式的一个例子。如果您(是的,您正在阅读)认为我错了,请在下面评论并让我知道。我对什么构成策略模式的“纯”用途以及实现的哪些方面违反了定义感到好奇。我认为这看起来有点可笑,因为策略界面有点胖。到目前为止,我所看到的所有示例都仅使用一种方法,但是我仍然认为它封装了一种算法(如果可以将某种业务逻辑视为一种算法,我认为它确实可以)。

由于该策略还会在交付执行过程中收到有关事件的通知,因此也可以将其视为观察者,但这是另一回事了。

通过进行一些研究,似乎这是一个称为“ 顾问 ”的“复合模式”(例如MVC,该模式以特定方式在其下使用多个设计模式)。它是有关是否应继续传送的顾问,但它也是一个主动的错误处理程序,因为它可以在被要求时回滚内容。

无论如何,这是一个非常复杂的示例,可能使您感到策略模式的使用太简单/愚蠢。与其他模式一起使用时,它可能真的很复杂,甚至更适用。


6

策略模式是最常用的模式,专门用于验证和排序算法。

让我用一个简单的实际例子来解释

enum Speed {
  SLOW, MEDIUM, FAST;
}

class Sorter {
 public void sort(int[] input, Speed speed) {
    SortStrategy strategy = null;
    switch (speed) {
    case SLOW:
        strategy = new SlowBubbleSortStrategy();
        break;
    case MEDIUM:
        strategy = new MediumInsertationSortStrategy();
        break;

    case FAST:
        strategy = new FastQuickSortStrategy();
        break;
    default:
        strategy = new MediumInsertationSortStrategy();
    }
    strategy.sort(input);
 }

}

interface SortStrategy {

    public void sort(int[] input);
}

class SlowBubbleSortStrategy implements SortStrategy {

   public void sort(int[] input) {
    for (int i = 0; i < input.length; i++) {
        for (int j = i + 1; j < input.length; j++) {
            if (input[i] > input[j]) {
                int tmp = input[i];
                input[i] = input[j];
                input[j] = tmp;
            }
        }
    }
    System.out.println("Slow sorting is done and the result is :");
    for (int i : input) {
        System.out.print(i + ",");
    }
  }

 }

class MediumInsertationSortStrategy implements SortStrategy {

public void sort(int[] input) {
    for (int i = 0; i < input.length - 1; i++) {
        int k = i + 1;
        int nxtVal = input[k];
        while (input[k - 1] > nxtVal) {
            input[k] = input[k - 1];
            k--;
            if (k == 0)
                break;
        }
        input[k] = nxtVal;
    }
    System.out.println("Medium sorting is done and the result is :");
    for (int i : input) {
        System.out.print(i + ",");
    }

 }

}

class FastQuickSortStrategy implements SortStrategy {

public void sort(int[] input) {
    sort(input, 0, input.length-1);
    System.out.println("Fast sorting is done and the result is :");
    for (int i : input) {
        System.out.print(i + ",");
    }
}

private void sort(int[] input, int startIndx, int endIndx) {
    int endIndexOrig = endIndx;
    int startIndexOrig = startIndx;
    if( startIndx >= endIndx)
        return;
    int pavitVal = input[endIndx];
    while (startIndx <= endIndx) {
        while (input[startIndx] < pavitVal)
            startIndx++;
        while (input[endIndx] > pavitVal)
            endIndx--;
        if( startIndx <= endIndx){
            int tmp = input[startIndx];
            input[startIndx] = input[endIndx];
            input[endIndx] = tmp;
            startIndx++;
            endIndx--;
        }
    }
    sort(input, startIndexOrig, endIndx);
    sort(input, startIndx, endIndexOrig);
 }

}  

测试代码是

public class StrategyPattern {
  public static void main(String[] args) {
    Sorter sorter = new Sorter();
    int[] input = new int[] {7,1,23,22,22,11,0,21,1,2,334,45,6,11,2};
    System.out.print("Input is : ");
    for (int i : input) {
        System.out.print(i + ",");
    }
    System.out.println();
    sorter.sort(input, Speed.SLOW);
 }

}

相同的示例来自http://coder2design.com/strategy-pattern/


策略模式的不同用法:验证:在代码中需要进行大量验证时。不同的算法:特别是当可以使用不同的排序算法时,例如气泡排序或快速排序。存储信息:当我们可能在其他地方(例如数据库或文件系统)提供信息时。解析:解析时,我们可以对不同的输入使用不同的策略。过滤策略。布局策略。
Jatinder Pal

5

策略模式的一个很好的例子是在一个游戏中,我们可以拥有不同的角色,每个角色可以拥有多种武器来进攻,但一次只能使用一种武器。因此,我们以角色为背景,例如,国王,司令,骑士,士兵和武器为战略,其中Attack()可能是取决于所使用武器的方法/算法。因此,如果具体的武器类别是Sword,Axe,Crossbow,BowAndArrow等。它们都将实现Attack()方法。我确信不需要进一步的解释。


1
我以为接受的答案应该是关于这个例子的:)
Jeancarlo Fontalvo

2

我在一个应用程序的相当复杂的引擎中使用了策略方法,这就是一个很好的例子。本质上,引擎的作用是去找到拥有微件的人员列表,第二个作用是根据未知数量的参数(例如价格,距离,以前的生意在一起)找出哪些是拥有微件的10位最佳人员。 ,库存量,运输选项等等等...)

本质上,我们所做的就是将问题分为两种策略,第一种是数据检索,因为我们知道我们有多个小部件来源,我们需要能够获取数据并将其转换为通用结构。

然后我们还意识到,我们有多个算法,其中一些是基于对参数的加权,另一些则非常怪异和挑剔,如果不拉出visios和图表,我就无法做到公平,那么您就会明白了,我们有很多算法选择最好的人。

我们的服务本身非常重要,它本质上定义了输入,输出并对数据进行了一些标准化,它还使用了提供程序模式来插入使用该策略的特定于应用程序的数据提供程序和算法提供程序。这是一个相当有效的系统。

如果我们使用从未解决过的策略或模板模式,我们会进行一些辩论。


2

您确定“订单”的状态不是国家模式吗?我有一种预感,即根据订单的状态不会对订单进行不同的处理。

以方法“按订单发货”为例:

order.Ship();
  • 如果运送方法的状态功能有所不同,那么您就有了一种策略模式。
  • 但是,如果Ship()方法仅在订单已付款且订单尚未发货时才成功,则您具有状态模式。

我发现的状态模式(和其他模式)的最好例子是在“ Head First Design Patterns书中,这真是了不起。紧随其后的David Cumps的博客系列模式


2

假设您要编写一种算法来计算给定月份和年份的第n个Xday,例如,2014年10月的第二个星期一。您要使用Android的Time类android.text.format.Time来表示日期,但是还想编写一个通用算法这也适用于java.util.Calendar

这就是我所做的。

在DatetimeMath.java中:

public interface DatetimeMath { 
    public Object createDatetime(int year, int month, int day);

    public int getDayOfWeek(Object datetime);

    public void increment(Object datetime);
}

在TimeMath.java中:

public class TimeMath implements DatetimeMath {
    @Override
    public Object createDatetime(int year, int month, int day) {
        Time t = new Time();
        t.set(day, month, year);
        t.normalize(false);
        return t;
    }

    @Override
    public int getDayOfWeek(Object o) {
        Time t = (Time)o;
        return t.weekDay;
    }   

    @Override
    public void increment(Object o) {
        Time t = (Time)o;
        t.set(t.monthDay + 1, t.month, t.year);
        t.normalize(false);
    }
}

在OrdinalDayOfWeekCalculator.java中,具有通用算法的类:

public class OrdinalDayOfWeekCalculator {   
    private DatetimeMath datetimeMath;

    public OrdinalDayOfWeekCalculator(DatetimeMath m) {
        datetimeMath = m;
    }

    public Object getDate(int year, int month, int dayOfWeek, int ordinal) {
        Object datetime = datetimeMath.createDatetime(year, month, 1);
        if (datetimeMath.getDayOfWeek(datetime) == dayOfWeek) {
            return datetime;
        } 
        int xDayCount = 0;
        while (xDayCount != ordinal) {
            datetimeMath.increment(datetime);
            if (datetimeMath.getDayOfWeek(datetime) == dayOfWeek) {
                xDayCount++;
            }
        }
        return datetime;
    }
}

在我的Android应用中,我会称呼类似

OrdinalDayOfWeekCalculator odowc = 
        new OrdinalDayOfWeekCalculator(new TimeMath());
Time canadianThanksgiving = (Time)odowc.getDate(
        year, Calendar.OCTOBER, Time.MONDAY, 2);

如果要为重复使用相同的算法java.util.Calendar,则只需编写一个实现了DatetimeMath中的三个方法的CalendarMath类,然后使用

OrdinalDayOfWeekCalculator odowc2 = 
        new OrdinalDayOfWeekCalculator(new CalendarMath());
Calendar canadianThanksgivingCal = (Calendar)odowc2.getDate(
        year, Calendar.OCTOBER, Calendar.MONDAY, 2);

2
public class StrategyDemo {
    public static void main(String[] args) {
        ShoppingCart cart = new ShoppingCart();

        Item item1 = new Item("1234", 10);
        Item item2 = new Item("5678", 40);

        cart.addItem(item1);
        cart.addItem(item2);

        // pay by paypal
        cart.pay(new PaypalStrategy("myemail@example.com", "mypwd"));

        // pay by credit card
        cart.pay(new CreditCardStrategy("Pankaj Kumar", "1234567890123456", "786", "12/15"));
    }
}

interface PaymentStrategy {
    public void pay(int amount);
}

class CreditCardStrategy implements PaymentStrategy {

    private String name;
    private String cardNumber;
    private String cvv;
    private String dateOfExpiry;

    public CreditCardStrategy(String nm, String ccNum, String cvv, String expiryDate) {
        this.name = nm;
        this.cardNumber = ccNum;
        this.cvv = cvv;
        this.dateOfExpiry = expiryDate;
    }

    @Override
    public void pay(int amount) {
        System.out.println(amount + " paid with credit/debit card");
    }

}

class PaypalStrategy implements PaymentStrategy {

    private String emailId;
    private String password;

    public PaypalStrategy(String email, String pwd) {
        this.emailId = email;
        this.password = pwd;
    }

    @Override
    public void pay(int amount) {
        System.out.println(amount + " paid using Paypal.");
    }

}

class Item {

    private String upcCode;
    private int price;

    public Item(String upc, int cost) {
        this.upcCode = upc;
        this.price = cost;
    }

    public String getUpcCode() {
        return upcCode;
    }

    public int getPrice() {
        return price;
    }

}

class ShoppingCart {

    // List of items
    List<Item> items;

    public ShoppingCart() {
        this.items = new ArrayList<Item>();
    }

    public void addItem(Item item) {
        this.items.add(item);
    }

    public void removeItem(Item item) {
        this.items.remove(item);
    }

    public int calculateTotal() {
        int sum = 0;
        for (Item item : items) {
            sum += item.getPrice();
        }
        return sum;
    }

    public void pay(PaymentStrategy paymentMethod) {
        int amount = calculateTotal();
        paymentMethod.pay(amount);
    }
}

1

几周前,我添加了一个通用的Java接口,该接口由我们的域对象之一实现。该域对象是从数据库中加载的,数据库表示形式是具有约10个以上分支的星型模式。具有如此繁重的域对象的后果之一是,我们不得不制作其他代表相同架构的域对象,尽管它们的重量较轻。因此,我使其他轻量级对象实现了相同的接口。换句话说,我们有:

public interface CollectibleElephant { 
    long getId();
    String getName();
    long getTagId();
}

public class Elephant implements CollectibleElephant { ... }
public class BabyElephant implements CollectibleElephant { ... }

最初,我想使用CollectibleElephant排序Elephant。很快,我的队友们凝视CollectibleElephant着进行安全检查,在将其发送到GUI时对其进行过滤等。


1

我们必须为具有非常复杂的数据库的企业平台创建第三方供应接口。要提供的数据的提交是我们的数据类型的列表,这些数据类型被放入应用程序的优先级队列中,因此由于依赖关系,它们可以按正确的顺序写入数据库。

这样,写入数据的过程就非常简单,不断从优先级队列的顶部弹出,然后根据提取的对象的类型选择策略。


0

来自维基百科

在计算机编程中,策略模式(也称为策略模式)是一种行为软件设计模式,可以在运行时选择算法。代码不是直接实现单个算法,而是接收运行时指令,说明要使用的算法系列中的哪个

在Windows Paint应用程序中,您可以看到策略模式,您可以在其中选择不同部分中的形状和颜色。这里的形状和颜色是可以在运行时更改的算法。

如果要绘制红色的圆形,而不是提供“ RedCircle”选项,则可以选择圆形和自己选择的颜色。

Shape redCircle = new RedCircle(); // Without stretegy Pattern
Shaped redCircle = new Shape("red","circle"); // With Strategy pattern

如果没有策略模式,则形状和颜色的笛卡尔积会增加类别的数量。接口也将针对每个实现而更改。


0

想象一下与AI敌人进行的射击游戏。您希望他们根据发生的事情以不同的方式持续战斗。通过策略模式,您可以不断循环并动态更改执行特定或动作的方式。

interface FightingStategy{
    public void fight();
}
public Defense implements FightingStrategy{
    public void figth(){
        ... hide behind wall to shoot
    }
}
public Berserker implements FightingStrategy{
    public void fight(){
        ... run towards you, headrolls and shoots
    }
}
public Dead implements FightingStrategy{
    public void fight(){
        ... is dead, doesn't move
    }
}

public AiShooter{

    FightingStrategy fightingStrategy;

    public AiShooter(){
        fightStrategy = new Berserker();
    }

    public void fight(){
        this.fightingStrategy.fight();
    }

    public void changeStrategy(FightingStrategy f){
        this.fightingStrategy = f;
    }
}

public static void main(){

    ... create list of AiShooters...
    while (condition){
        list.forEach(shooter -> shooter.fight());
    }
    ... you shoot back
    list.ForEach(shooter -> shooter.changeStrategy(new 
Defense()));

    ... you kill one
    list.get(n).changeStrategy(new Dead());
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.