Java 方法数组:适配器模式?
问题描述: 我希望能够将方法列表传递给只在一个类中定义了方法的其他类。如果在一个类中定义了方法,其中一些方法具有输入参数和非void返回类型,我希望能够将其中一些方法的列表(可能有重复项)作为参数传递给其他类的构造函数 代码说明: 下面的代码是一个粗糙的示例,如果它偏离了主要目标,则可以忽略它。除了下面的例子之外,另一个例子是方法为int-Add(int-n1,int-n2)、int-Subtract(int-n1,int-n2)、Multiply等。。接口有一个名为int-MathOperation的方法(int-n1,int-n2) 尝试解决问题: 适配器模式似乎具有我正在寻找的功能,但我只看到接口中的方法没有输入或输出参数的示例。下面是我为这个问题编写的一个示例实现 问题类比: 您有一个随机图片生成器web服务。有30种突变可以应用于图像。客户端连接并单击“生成”按钮,其中一些函数的随机列表被传递给web服务中的其他类,然后这些类继续使用自己的数据运行这些函数,同时还收集并可能重新使用返回值来生成一些变异的cat映像。它不能只显式调用另一个类中的方法,因为该过程需要在运行时随机完成。这就是为什么我倾向于生成一个随机的方法列表,这些方法在单击“生成”按钮时按顺序执行 我希望我已经说清楚了Java 方法数组:适配器模式?,java,design-patterns,adapter,Java,Design Patterns,Adapter,问题描述: 我希望能够将方法列表传递给只在一个类中定义了方法的其他类。如果在一个类中定义了方法,其中一些方法具有输入参数和非void返回类型,我希望能够将其中一些方法的列表(可能有重复项)作为参数传递给其他类的构造函数 代码说明: 下面的代码是一个粗糙的示例,如果它偏离了主要目标,则可以忽略它。除了下面的例子之外,另一个例子是方法为int-Add(int-n1,int-n2)、int-Subtract(int-n1,int-n2)、Multiply等。。接口有一个名为int-MathOperat
public class SomeClass {
...
public double UseWrench(double torque, boolean clockwise) { ... }
public double UsePliers(double torque, boolean clockwise) { ... }
public double UseScrewDriver(double torque, boolean clockwise) { ... }
public boolean UseWireCutters(double torque) { ... }
interface IToolActions {
double TurnFastener(double torque, boolean clockwise);
boolean CutWire(double torque);
}
private IToolActions[] toolActions = new IToolActions[] {
new IToolActions() { public double TurnFastener(double torque, boolean clockwise) { double UseWrench(double torque, boolean clockwise); } },
new IToolActions() { public double TurnFastener(double torque, boolean clockwise) { double UsePliers(double torque, boolean clockwise); } },
new IToolActions() { public double TurnFastener(double torque, boolean clockwise) { double UseScrewDriver(double torque, boolean clockwise); } },
new IToolActions() { public boolean CutWire(double torque) { boolean UseWireCutters(double torque); } },
};
}
public class Worker<T> {
public List<? extends IToolActions> toolActions;
public Worker(List<? extends IToolActions> initialToolSet){
toolActions = initialToolActions;
}
}
公共类SomeClass{
...
公用两用扳手(双扭矩,布尔顺时针){…}
公用双用钳(双扭矩,布尔顺时针){…}
公用两用螺丝刀(双扭矩,布尔顺时针){…}
公共线切割机(双扭矩){…}
接口冲突{
双旋转紧固件(双扭矩,布尔顺时针);
布尔切割线(双扭矩);
}
私有iToolations[]工具操作=新iToolations[]{
新的iToolations(){公共双转紧固件(双扭矩,布尔顺时针){双用扳手(双扭矩,布尔顺时针);},
新的iToolations(){公共双转紧固件(双扭矩,布尔顺时针){双用钳子(双扭矩,布尔顺时针);},
新的iToolations(){公共双转紧固件(双扭矩,布尔顺时针){双用螺丝刀(双扭矩,布尔顺时针);},
新的iToolations(){public boolean CutWire(双扭矩){boolean usewirecutors(双扭矩);},
};
}
公社工人{
公共列表@John以下是我如何找到解决你问题的方法
我使用了MathOperations的例子来简化它。首先,我认为最好将接口放在某个类之外,如:
public interface MathOperable {
public int mathOperation(int n1, int n2);
}
我创建了两个实现此接口的类的示例,以及SomeClass中的一个匿名实现(我做了一个加法、乘法和一个匿名“减法”)
下面是几个执行死刑的例子:
还有另一个例子
我希望这会有帮助!虽然@alainlompo有一个大致的想法,但Java 8通过对类对象使用诸如BiConsumer
(双倍)或甚至仅仅是消费者
,大大简化了这一点。事实上,您可能会非常疯狂,并且有一个方法接受varargs lambdas:
public class SomeClass
public double useWrench(double torque, boolean clockwise) { ... }
public double usePliers(double torque, boolean clockwise) { ... }
public double useScrewDriver(double torque, boolean clockwise) { ... }
public boolean useWireCutters(double torque) { ... }
}
public class Worker {
@SafeVarargs
public Worker(SomeClass example, Consumer<? extends SomeClass>... operations) {
for (Consumer bc : operations) {
bc.accept(example);
}
}
}
虽然像这样应用它似乎有点尴尬(因为它是一种适配器模式),但您可以很容易地看到它是如何应用于类主体的:
public class SomeClass
public double useWrench(double torque, boolean clockwise) { ... }
public double usePliers(double torque, boolean clockwise) { ... }
public double useScrewDriver(double torque, boolean clockwise) { ... }
public boolean useWireCutters(double torque) { ... }
@SafeVarargs
public void operate(Consumer<? extends SomeClass>... operations) {
for (Consumer<? extends SomeClass> bc : operations) {
bc.accept(example);
}
}
}
//Elsewheres
SomeClass c = new SomeClass();
c.operate(SomeClass::useWrench, SomeClass:usePliers, SomeClass::useScrewDriver, SomeClass::useWireCutters);
java 8中的函数API提供了更大的灵活性,使类似这样的复杂问题的编写变得极其简单。好的,我将成为“那个家伙”…一个理解问题,但无论如何都要重申问题的人,因为我认为你走错了路。所以,请容忍我:如果你喜欢你所看到的,很好;如果不喜欢,我理解
基本上,您的意图/动机/目的与“适配器”的用途不同。命令模式更适合
但首先,更一般地说,设计“可重用软件的元素”(源于原始GOF设计模式书的标题)的目标之一是,您不希望在添加功能时修改代码;相反,您希望添加代码而不触及现有功能。因此,当您:
public class Toolbox {
public void hammer() { ... }
}
如果您想在工具箱中添加螺丝刀,这很糟糕:
public class Toolbox {
public void hammer() { ... }
public void screwdriver() { ... }
}
相反,理想情况下,所有现有代码都将保持不变,您只需添加一个新的编译单元(即,添加一个新文件)和一个单元测试,然后测试现有代码进行回归(这不太可能,因为现有代码都没有更改)。例如:
public class Toolbox {
public void useTool(Tool t) { t.execute(); ...etc... }
}
public interface Tool { // this is the Command interface
public void execute() // no args (see ctors)
}
public Hammer implements Tool {
public Hammer(Nail nail, Thing t) // args!
public void execute() { nail.into(t); ... }
}
public Screwdriver implements Tool {
public Screwdriver(Screw s, Thing t)
public void execute() { screw.into(t); ... }
}
希望您能够清楚地了解如何将其扩展到您的示例中。工作人员将成为直接向前的工具列表(或者,为了清楚起见,将其称为“命令”,而不是“工具”)
公共类工作者{
公开名单行动清单;
....
公共工程(){
对于(…){
action.execute();
}
}
}
此模式还允许轻松的“撤消”功能和“重试”,以及记忆(缓存结果,以便不必重新运行).我想我知道你在追求什么,但我需要一个更好的问题描述或更好的例子。停顿似乎是方法参数和返回值。你必须定义一些方法来处理这些问题,你的特定需求将决定需要如何工作。没有通用的“X”总是解决这类问题。也许可以解释一下你遇到了什么问题
public class SomeClass
public double useWrench(double torque, boolean clockwise) { ... }
public double usePliers(double torque, boolean clockwise) { ... }
public double useScrewDriver(double torque, boolean clockwise) { ... }
public boolean useWireCutters(double torque) { ... }
}
public class Worker {
@SafeVarargs
public Worker(SomeClass example, Consumer<? extends SomeClass>... operations) {
for (Consumer bc : operations) {
bc.accept(example);
}
}
}
SomeClass c = new SomeClass();
new Worker(c, SomeClass::useWrench, SomeClass:usePliers, SomeClass::useScrewDriver, SomeClass::useWireCutters);
public class SomeClass
public double useWrench(double torque, boolean clockwise) { ... }
public double usePliers(double torque, boolean clockwise) { ... }
public double useScrewDriver(double torque, boolean clockwise) { ... }
public boolean useWireCutters(double torque) { ... }
@SafeVarargs
public void operate(Consumer<? extends SomeClass>... operations) {
for (Consumer<? extends SomeClass> bc : operations) {
bc.accept(example);
}
}
}
//Elsewheres
SomeClass c = new SomeClass();
c.operate(SomeClass::useWrench, SomeClass:usePliers, SomeClass::useScrewDriver, SomeClass::useWireCutters);
public class SomeClass {
public double chanceOfSuccess(Function<? super SomeClass, ? extends Double> modifier) {
double back = /* some pre-determined result */;
return modifier.apply(back); //apply our external modifier
}
}
//With our old 'c'
double odds = c.chanceOfSuccess(d -> d * 2); //twice as likely!
public class Toolbox {
public void hammer() { ... }
}
public class Toolbox {
public void hammer() { ... }
public void screwdriver() { ... }
}
public class Toolbox {
public void useTool(Tool t) { t.execute(); ...etc... }
}
public interface Tool { // this is the Command interface
public void execute() // no args (see ctors)
}
public Hammer implements Tool {
public Hammer(Nail nail, Thing t) // args!
public void execute() { nail.into(t); ... }
}
public Screwdriver implements Tool {
public Screwdriver(Screw s, Thing t)
public void execute() { screw.into(t); ... }
}
public class Worker {
public List<Command> actionList;
....
public void work() {
for(...) {
action.execute();
}
}
}