使用策略模式,如何根据具有不同参数的不同执行方法来区别对待?
3 个策略示例
public function execute(string $param1, string $param2)
{
// Do something specific to this method
//
// Do some generic things across all strategies
//
}
public function execute(string $param1)
{
// Do something specific to this method
//
// Do some generic things across all strategies
//
}
public function execute()
{
// Do something specific to this method
//
// Do some generic things across all strategies
}
Run Code Online (Sandbox Code Playgroud)
所有这些都做了一些非常具体的事情,但需要不同的参数,然后他们做了一些每个策略都会做的通用事情。
我正在尝试使用服务的策略模式,但是我尝试用作策略上下文的模块似乎只坚持两者之一。这是示例代码:
动物模块.ts
@Module({})
export class AnimalModule {
static register(strategy): DynamicModule {
return {
module: AnimalModule,
providers: [{ provide: 'STRATEGY', useValue: strategy }, AnimalService],
imports: [],
exports: [AnimalService]
};
}
}
Run Code Online (Sandbox Code Playgroud)
动物服务.ts
@Injectable()
export class AnimalService {
constructor (@Inject('STRATEGY') private strategy) {
this.strategy = strategy
}
public makeSound() {
return this.strategy.makeSound()
}
}
Run Code Online (Sandbox Code Playgroud)
猫模块.ts
@Module({
imports: [
AnimalModule.register(catStrategy),
],
controllers: [CatController],
providers: [CatService],
})
export class CatModule {}
Run Code Online (Sandbox Code Playgroud)
猫服务.ts
@Injectable()
export class CatService {
constructor(
private readonly animalService: AnimalService,
) {} …Run Code Online (Sandbox Code Playgroud) 在实现了策略模式之后,我想创建一个接口类型的数组,然后我可以添加任何具体类型.
对于那些不了解策略模式的人:http: //en.wikipedia.org/wiki/Strategy_pattern 在这个特定的例子中,我想创建一个StrategyInterface数组,然后我可以填充具体类型的A,B和C但是,因为这是一个抽象类,我无法完成它.如果没有删除抽象方法,有没有办法做到这一点,还是完全不可能?
考虑
Action _captureAction;
private void TestSimpleCapturedAction()
{
Action action = new Action(delegate { });
Action printAction = () => Console.WriteLine("Printing...");
action += printAction;
CaptureActionFromParam(action);
action -= printAction;
_captureAction(); //printAction will be called!
}
private void CaptureActionFromParam(Action action)
{
_captureAction = () => action();
}
Run Code Online (Sandbox Code Playgroud)
printAction将由_captureAction调用的原因是该行
action -= printAction;
Run Code Online (Sandbox Code Playgroud)
实际上翻译成
action = (Action) Delegate.Remove(action, printAction);
Run Code Online (Sandbox Code Playgroud)
因此,CaptureActionFromParam()中_captureAction捕获的操作不会更改 - 只会影响TestSimpleCapturedAction()中的本地"action"变量.
在这种情况下我想要的行为是printAction没有被调用.我能想到的唯一解决方案是定义一个新的"委托容器"类:
class ActionContainer
{
public Action Action = new Action(delegate { });
}
private void TestCapturedActionContainer()
{
var actionContainer = new ActionContainer();
Action …Run Code Online (Sandbox Code Playgroud) 我理解"战略模式"的概念,但我仍然有点困惑.
我们有一个名为的班级Dog.
Dog有MovementBehaviour(接口)可以MovementBehaviourNormal和MovementBehaviourFast.
MovementBehaviourNormal并且MovementBehaviourFast都包含一个名为的方法move.
问题:从move方法中访问dog属性的最佳方法是什么?将狗对象传递MovementBehaviour给委托是不是一个坏主意?
我正在使用需要接收多个视频的应用程序,并将其显示在特定页面上,目前这些视频只能来自YouTube,因为实现不允许其他提供商,因为获取视频数据的代码作为预览图像,直接放置在负责显示视频的View Helper中.
我想改变这种结构,可以很容易地添加新的供应商,如Vimeo的,我认为策略模式将是理想的,我会在我的视图助手的方法setVideoUrl( string $url ),这种方法会调用该方法getProviderStrategy( string $url )从class VideoProviderFactory,这然后,工厂类将返回策略类(如果可用),该类interface VideoProvider为视频URL的提供者实现.
你怎么看?这是对的?我需要改变什么?
细节:我最初考虑过将一个开关直接选择到View Helper中,但在阅读完这个问题之后:我没有'switch'语句的策略模式?我看到我错了,然后class VideoProviderFactory出现了.
php language-agnostic design-patterns strategy-pattern factory-pattern
在OO世界中,我有一个类(我们称之为"Suggestor"),它实现接近"策略模式"的东西,以在运行时提供不同的算法实现.作为学习Haskell的练习,我想重写一下.
实际的用例非常复杂,所以我将简单介绍一个简单的例子.
假设我有一个Suggester列出规则列表的类,并将每个规则作为过滤器应用于数据库结果列表.
每个规则都有三个阶段"构建查询","后查询过滤器"和"记分器".我们最终会得到满足以下要求的界面
buildQuery :: Query -> Query
postQueryFilter :: [Record] -> [Record]
scorer :: [Record] -> [(Record, Int)]
Run Code Online (Sandbox Code Playgroud)
Suggestor需要获取与此接口匹配的规则列表 - 在运行时动态 - 然后按顺序执行它们.必须首先在所有规则中运行buildQuery(),然后是postQueryFilter,然后是scorer.(即我不能只将一个规则的函数组合成一个函数).
在斯卡拉我只是做
// No state, so a singleton `object` instead of a class is ok
object Rule1 extends Rule {
def buildQuery ...
def postQueryFilter ...
def scorer ...
}
object Rule2 extends Rule { .... }
Run Code Online (Sandbox Code Playgroud)
然后可以通过传递相关规则来初始化服务(在运行时根据用户输入定义).
val suggester = new Suggester( List(Rule1, Rule2, Rule3) );
Run Code Online (Sandbox Code Playgroud)
如果规则是单个函数,那么这很简单 - 只需传递一个函数列表.但是,由于每个规则实际上是三个函数,我需要以某种方式将它们组合在一起,所以我有多个实现会议接口.
我的第一个想法是类型类,但是这些似乎不能满足我的需求 - 他们期望一个类型变量,并强制我的每个方法必须使用它 - …
给定典型的策略模式
class Strategy
{
public:
virtual int execute() const = 0;
}
class StrategyA : public Strategy
{
public:
int execute() const override;
}
class StrategyB : public Strategy
{
public:
int execute() const override;
}
Run Code Online (Sandbox Code Playgroud)
我相信实现上下文类的“ pre-C ++ 11”方式将类似于
class ContextRaw
{
public:
ContextRaw(Strategy* the_strategy);
~ContextRaw(); // Should this delete the_strategy_?
int execute() const;
private:
Strategy* the_strategy_;
}
Run Code Online (Sandbox Code Playgroud)
对我来说,在这种设计中,尚不清楚是否Context应对负责Strategy,除非有明确的文档说明,否则,可能会发生不好的事情
void trouble()
{
StrategyA a_concrete_strategy;
ContextRaw a_context(&a_concrete_strategy); // Oops, Context may try to delete stack variable …Run Code Online (Sandbox Code Playgroud) 假设我有一个实用程序类。在本课程中,我仅公开 2 个公共函数:
\n\npublic static boolean checkCustomerEligiblity(HttpServletRequest request)\npublic static boolean checkCartEligiblity(HttpServletRequest request)\nRun Code Online (Sandbox Code Playgroud)\n\n这些方法\xe2\x80\x99s的实现真的很乱(我没有实现这个方法)。为了供将来参考,我想了解在这种情况下我们可以实施的最佳方法。
\n\n还要记住的是,如果条件为 FALSE,我们不应该退出或返回。我们必须记录 FALSE 条件并给出原因,然后继续进行其余的检查。
\n\npublic static Boolean checkCustomerEligiblity(HttpServletRequest request) {\n if (Flags) { //Check if Flags are ON, only then proceed with rest \n if (Type of customer) { //Restrict only to certain type of customers\n if (Customer within limit) { //Check customer\xe2\x80\x99s available cash limit in account\n\n } else reasons.add(\xe2\x80\x9cCustomer not within limit\xe2\x80\x9d);\n } else reasons.add(\xe2\x80\x9cCustomer type not supported\xe2\x80\x9d);\n\n if (Customer account …Run Code Online (Sandbox Code Playgroud)