标签: strategy-pattern

这段代码太脆了吗?

我需要创建一个策略模式,用户从二十或三十个唯一策略对象的列表中选择四个策略.随着项目的成熟,策略列表将会扩展,用户可以随时更改所选策略.

我打算将他们选择的策略名称存储为字符串,然后使用类似这样的方法来加载与他们选择的字符串相对应的策略类.

class StrategyManager { // simplified for the example
    public $selectedStrategies = array();
    public function __construct($userStrategies) {
        $this->selectedStrategies = array(
            'first'  => new $userStrategies['first'],
            'second' => new $userStrategies['second'],
            'third'  => new $userStrategies['third'],
            'fourth' => new $userStrategies['fourth']
        );
    }

    public function do_first() {
        $this->selectedStrategies['first']->execute();
    }

    public function do_second() {
        $this->selectedStrategies['second']->execute();
    }

    public function do_third() {
        $this->selectedStrategies['third']->execute();
    }

    public function do_fourth() {
        $this->selectedStrategies['fourth']->execute();
    }
}
Run Code Online (Sandbox Code Playgroud)

我试图避免一个大的switch语句.我担心的是,这似乎有点儿Stringly Typed.有没有更好的方法来实现这个目标而不使用条件或大型switch语句?

BTW:用户在选择四种策略时不输入字符串.我需要维护一个字符串列表,以便在选择框中向用户显示,并在添加新策略对象时将新的字符串添加到列表中.

解释
ircmaxell表达了一些关于我正在尝试做什么的混淆.在上面的示例中,用户从列表中选择了四个策略,并将它们作为字符串数组传递给StrategyManager构造函数.创建相应的策略对象并将其存储在内部数组中,$this->selectedStrategies

"第一","第二","第三"和"第四"是用于四种不同选定策略的内部阵列的数组键.在构建StrategyManager对象之后,应用程序execute在整个过程的生命周期中的各个时刻使用四种策略的方法.

因此,简而言之......每次应用程序需要执行策略编号"one"的方法时,它都会这样做,并且结果会有所不同,具体取决于用户为策略"one"选择的策略

php string strategy-pattern

5
推荐指数
1
解决办法
182
查看次数

如何将'this'作为参数传递给另一个没有循环依赖的类构造函数?

我正在考虑策略模式(Design Patterns,GoF94),其中建议传递给策略构造函数的上下文可以是包含策略(作为成员)本身的对象.但以下方法不起作用:

//analysis.h

class StrategyBase;
class Strategy1;
class Strategy2;
class Analysis
{
   ...
      void ChooseStrategy();
   private:
      StrategyBase* _s;
      ...
};

//analysis.cpp

void Analysis::ChooseStrategy()
{
   if (...) _s = new Strategy1(this);
   else if (...) _s = new Strategy2(this);
   ...
}

//strategy.h

#include analysis.h
...
Run Code Online (Sandbox Code Playgroud)

然后StrategyBase及其子类访问Analysis的数据成员.

这不起作用,因为您无法在定义之前实例化Strategy*类.但它的定义取决于分析的定义.那么你应该怎么做呢?将ChooseStrategy替换为

void SetStrategy(StrategyBase* s) { _s = s; }
Run Code Online (Sandbox Code Playgroud)

并在#include analysis.h和strategy.h的文件中进行实例化?这里最好的做法是什么?

c++ dependencies include strategy-pattern

5
推荐指数
2
解决办法
812
查看次数

模板方法和策略设计模式之间有什么相似之处

这是TemplateMethod Pattern的一个例子吗?

public abstract class Character{

    public final void useWeapon(){
        useBusterSword();
        useMateriaBlade();
        useUltimateWeapon();
    }

    public abstract void useBusterSword();
    public abstract void useMateriaBlade();
    public abstract void useUltimateWeapon();
}

public class Cloud extends Character{

    public void useUltimateWeapon() {
        System.out.println("Change Weapon to Ultima Weapon");
    }


    public void useBusterSword() {

    }


    public void useMateriaBlade() {

    }
}


public class TestGame {
    public static void main(String[] args){
        Character cloud = new Cloud();
        cloud.useWeapon();
    }
}
Run Code Online (Sandbox Code Playgroud)

如果是这样,使用这种模式比战略模式有什么好处?

战略模式

public class Character {
    WeaponBehavior w;
    public void …
Run Code Online (Sandbox Code Playgroud)

java design-patterns strategy-pattern template-method-pattern

5
推荐指数
1
解决办法
1014
查看次数

移动策略:如何处理服务器-客户端版本排列?

我们正在为客户托管 SAAS 应用程序。主应用程序是一个网络应用程序,不同的客户端可以使用不同的版本。例如:

Company A  version 1.0
Company B  version 1.1
Run Code Online (Sandbox Code Playgroud)

我们在 App Store 中也有 Android/iOS 应用程序。由于应用程序并不总是最新的,因此我们在市场上也可以有多个应用程序版本。例如 2.0 和 2.1 。因此,出于兼容性原因,我们必须确保每个客户端版本都适用于每个服务器版本:

server 1.0 must work with client 2.0,
server 1.0 must work with client 2.1,
server 1.1 must work with client 2.0, 
and server 1.1 must work with client 2.2.
Run Code Online (Sandbox Code Playgroud)

当只有2个服务器版本和2个客户端版本时,这是可以管理的。然而,随着时间的推移,这个列表变得疯狂。我们确实有一种机制可以强制移动应用程序更新到最新版本,但这有点烦人,所以管理人员不想经常这样做。

我的问题是,处理这个问题的最佳策略是什么?Android和iOS是否有内置功能,用户可以下载多个应用程序版本,并且只根据需要启动一个版本?

提前致谢。

mobile web-services strategy-pattern

5
推荐指数
1
解决办法
529
查看次数

Java 策略模式 - 我可以在 Context 类中委托策略实例化吗?

我目前正在自学设计模式。当我研究策略模式时,我发现一些对我来说看起来很奇怪的东西。我查找了有关此模式的讨论,但没有人回答我的问题...这就是我如何实现策略模式以使其干净、保持封装并使添加新策略变得容易。这里解释我的问题是“规范”策略模式:

public interface Strategy {
    public void run();
}

public class stratConcrt1 implements Strategy {/*run() implementation*/}
public class stratConcrt2 implements Strategy {/*run() implementation*/}

public class Context {
    private Strategy strategy;

    public Context(Strategy strat) {
        this.strategy = strat;
    }

    public void runStrategy() {
        this.strategy.run()
    }
}


public class Client {
    public void main(Strings[] args) {
        Context cx;

        cx = new Context(new stratConcrt1())
        cx.runStrategy();

        cx = new Context(new stratConcrt2())
        cx.runStrategy();
    }
}
Run Code Online (Sandbox Code Playgroud)

我明白发生了什么,但让客户了解可以应用的不同策略,我感觉很奇怪。对我来说,让 Context 实例化不同的策略而不是 Client 会更干净,因为 Context 处理策略,它应该(至少在我看来)是唯一能够实例化策略的策略。

我使用 JavaFx 实现了一个小示例,与上面的代码有一些差异: …

java design-patterns strategy-pattern

5
推荐指数
1
解决办法
3603
查看次数

在使用设计模式时,您可以在多大程度上防止修改现有代码?

我正在学校参加设计模式课程,并阅读了Head First Design Patterns的一些章节.我想知道的是设计模式在多大程度上可以防止重写现有代码.

我们以Duck课程和FlyBehavior课程为例.我有public static void main(String[] args)以下代码:

Duck mallard = new MallardDuck(new FlyWithWings());
Run Code Online (Sandbox Code Playgroud)

我是否正确地说,main()当您想要添加新策略时,您不得不修改方法?这样,您正在修改现有代码,对吧?我特别指的是提到具体策略类的部分:new FlyWithWings().

如果在代码中实现了工厂方法模式,则可能会阻止具体的类(FlyWithWings)被提及:

public FlyBehavior returnBehavior(FlyBehaviorFactory factory, String behaviorType) {
    return factory.getFlyBehavior(behaviorType);
}
Run Code Online (Sandbox Code Playgroud)

因此,请使用以下代码行:

Duck mallard = new MallardDuck(returnBehavior(flyFactory, "wings"));
Run Code Online (Sandbox Code Playgroud)

这样,程序的某个部分不必知道要使用的FlyBehaviorFactory.但是,您的main()方法仍然需要在returnBehavior方法中指定某些参数,以便了解哪个工厂将创建什么策略.因此,我是否正确地说,main()如果我添加了一个新的FlyBehavior类,你仍然需要修改,并希望将其作为参数添加到returnBehavior()

可以进一步改善这种情况吗?

java methods design-patterns factory strategy-pattern

5
推荐指数
1
解决办法
76
查看次数

如何避免在 javascript (nodejs) 中使用大量 if-else

根据参数,函数应从 100 个 json 中选择一个 json 文件并向其他系统发出查询。

会有数百个查询。

显然, if else 和 switch 将无法管理。我在 javascript 中寻找了策略模式。

var queryCode = req.param('queryCode');

  if(queryCode == 'x'){
    //do something
  } else if( queryCode == 'y'){
    //do something
  } else if( queryCode == 'z') {
    //do something
  }
Run Code Online (Sandbox Code Playgroud)

// do something有时可能会变大......
所以我想用策略模式替换它。这将是最好的设计。预先感谢您对此问题的任何建议。

javascript design-patterns if-statement strategy-pattern node.js

5
推荐指数
1
解决办法
3786
查看次数

策略或适配器模式?

我想创建每个虚拟服务器提供程序的一些类,例如:

  • 数字海洋
  • 的Linode
  • 亚马逊AWS

每个Provider都有自己的PHP类(通过composer)来使用他们的API接口,我想使用他们的类库,但我想确保我可以为每个提供者使用相同的方法.例如关闭VPS:

  • Linode API方法: powerOff()
  • 数字海洋API方法: haltServer()

而不是使用powerOff()haltServer()- 我想为shutdown()我将创建的任何提供程序类使用方法.我应该使用策略设计还是适配器模式?

php design-patterns strategy-pattern adapter

5
推荐指数
1
解决办法
962
查看次数

合并使用不同对象的重复代码

我使用两个api调用来获取有关vehicleUtils的数据,具体取决于contentFilter.我有两个非常相似的代码(司机和车辆).我试图做的是将代码提取到一个单一的方法,并应用像他们在这里建议重构方法的策略模式,但我无法弄清楚如何实现它.我使用的是一种好方法还是有更好的方法?

if (contentFilter.equalsIgnoreCase(Contentfilters.VEHICLES.toString())) {

  VuScores vuScores = new VuScores();
  List<VehicleVuScores> vehicleVuScoresList = new ArrayList<>();
  List<VehicleUtilization> vehicleUtilizations = RestClient.getVehicles(request).join().getVehicleUtilizations();


  if (Objects.nonNull(vehicleUtilizations)) {
    vehicleUtilizations.forEach(vehicleUtilization -> {
      vuScores.getVehicleVuScores().forEach(vehicleVuScore -> {

        vehicleVuScore.getScores().setTotal(vehicleUtilization.getFuelEfficiencyIndicators().getTotal().getValue());
        vehicleVuScore.getScores().setBraking(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(3).getIndicators().get(0).getValue());
        vehicleVuScore.getScores().setCoasting(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(3).getIndicators().get(1).getValue());
        vehicleVuScore.getScores().setIdling(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(0).getIndicators().get(0).getValue());
        vehicleVuScore.getScores().setAnticipation(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(3).getValue());
        vehicleVuScore.getScores().setEngineAndGearUtilization(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(1).getValue());
        vehicleVuScore.getScores().setStandstill(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(0).getValue());
        vehicleVuScore.getScores().setWithinEconomy(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(1).getIndicators().get(7).getValue());
        vehicleVuScore.setAvgFuelConsumptionPer100Km(vehicleUtilization.getMeasures().getTotal().getAverageConsumption().getValue());
        vehicleVuScore.setAvgSpeedDrivingKmh(vehicleUtilization.getMeasures().getTotal().getAverageSpeed().getValue());
        vehicleVuScore.setEngineLoad(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(1).getIndicators().get(1).getValue());
        vehicleVuScore.setTotalDistanceInKm(vehicleUtilization.getMeasures().getDriving().getDistance().getValue());
        vehicleVuScore.setTotalTime(Math.toIntExact(vehicleUtilization.getMeasures().getTotal().getTime().getValue()));

        vehicleVuScoresList.add(vehicleVuScore);
      });
    });
    vuScores.setVehicleVuScores(vehicleVuScoresList);
  }
  return CompletableFuture.completedFuture(vuScores);

} else if (contentFilter.equalsIgnoreCase(Contentfilters.DRIVERS.toString())) {

  VuScores vuScores = new VuScores();
  List<DriverVuScores> driverVuScoresList = new ArrayList<>();
  List<VehicleUtilization> vehicleUtilizations = RestClient.getDrivers(request).join().getVehicleUtilizations();


  if (Objects.nonNull(vehicleUtilizations)) {
    vehicleUtilizations.forEach(vehicleUtilization -> {
      vuScores.getDriverVuScores().forEach(driverVuScores -> {

        driverVuScores.getScores().setTotal(vehicleUtilization.getFuelEfficiencyIndicators().getTotal().getValue());
        driverVuScores.getScores().setBraking(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(3).getIndicators().get(0).getValue());
        driverVuScores.getScores().setCoasting(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(3).getIndicators().get(1).getValue()); …
Run Code Online (Sandbox Code Playgroud)

java abstract-class design-patterns strategy-pattern

5
推荐指数
1
解决办法
75
查看次数

不同返回类型的 C# 策略设计模式

我尝试应用策略设计模式来解析一些文本内容,其中每个结果在不同的类中表示。

最小的例子。

所以我的界面是这样的:

public interface IParseStrategy
{
    object Parse(string filePath);
}
Run Code Online (Sandbox Code Playgroud)

实现算法的类:

class ParseA : IParseStrategy
{
    public object Parse(string filePath) => new ConcurrentQueue<ParseAData>();
}

class ParseB : IParseStrategy
{
    public object Parse(string filePath) => new Dictionary<string, ParseBData>();
}
Run Code Online (Sandbox Code Playgroud)

具体的“数据”类:

class ParseAData
{
    public int Id { get; set; }
    public string Name { get; set; }

}

class ParseBData
{
    private byte[] data;

    public byte[] GetData()
    {
        return data;
    }

    public void SetData(byte[] value)
    {
        data = value;
    } …
Run Code Online (Sandbox Code Playgroud)

c# strategy-pattern

5
推荐指数
1
解决办法
878
查看次数