我正在尝试在代码中实现策略模式,但是遇到了我所看到的示例中未涉及的内容。这就是策略需要引用父类中包含的方法的时候。
对于简单的示例(没有父引用),请使用Duck
和QuackBehaviour
示例:
class RubberDuck extends Duck {
public RubberDuck() {
setQuackBehaviour(new Squeak());
}
}
class Squeak implements QuackBehaviour {
public String quack() {
return "QUACK!";
}
}
但是如果我们现在有只鸭子喜欢说自己的名字怎么办?这意味着QuackBehaviour需要某种关于鸭子本身的引用。
class PsyDuck extends Duck {
public PsyDuck() {
setQuackBehaviour(new SayName(this));
}
}
class SayName implements QuackBehaviour {
private Duck duck;
public SayName(Duck duck) {
this.duck = duck;
}
public String quack() {
return duck.getName();
}
}
此气味对我来说像是错误的代码。这是反模式吗?它防止QuackBehaviour被非Duck对象重用。而且关于类之间的相互依赖关系,我不太满意。
我想您也可以将函数传递给PsyDuck
,例如:
class PsyDuck extends Duck {
public PsyDuck() {
setQuackBehaviour(new SayName(() => this.getName()));
}
}
但是,如果我们开始要求行为中包含多个字段,那么我们将必须传递许多函数参数。
或者最好让SayName
作为抽象类并让PsyDuck
实现具体的版本?
class PsyDuck extends Duck {
public PsyDuck() {
setQuackBehaviour(new PsyDuckSayName());
}
class PsyDuckSayName extends SayName {
protected String getName() {
return PsyDuck.this.getName();
}
}
}
abstract class SayName implements QuackBehaviour {
public String quack() {
return getName();
}
protected abstract String getName();
}
最后一种方法[[似乎最干净,但是我希望得到一些反馈和建议。
本身反模式。通常,您可以使用策略模式从类(或实例)外部提供“逻辑”,因此,如果以这种方式编写,则变得更加清晰(尽管直接在子类中使用也可以) :
Duck duck = new WhateverDuck();
duck.setQuackBehaviour(new SayNameBehaviour(duck));
// or:
duck.setQuackBehaviour(new MeowBehaviour());
因此,对于鸭子实现而言,如何实现嘎嘎无关紧要。如果实现需要鸭子引用来执行其工作-那就这样。如果不是-很好。[其他常用模式定义了“策略”实现所需的参数,因此您可以声明
quackBehaviour
例如作为Function<Duck, String>
类型。实现仍可以选择忽略该参数。但这对可能的(和不可能的)实现方式做出了一些假设,应谨慎使用。就您而言,我更喜欢第一个变体。