以下示例代码......
有没有办法chain instances of different classes
?提供的示例是尝试连接属于不同类实例的方法失败。
此外,在同一示例中,Client2
正在与Client3
共享错误对象。什么是sharing objects between subclasses and unassociated classes
的更有效方式?
为清楚起见,我也在内联评论。
感谢您的时间和帮助。
示例代码
public class StubRunner
{
public run(){
ClientFactory client = new ClientFactory();
//not correct. But, this is how i want to finally chain methods
//belonging to different class instances. Please advise.
client.getClient1().testClient1().getClient2().testClient2().assert(...);
}
}
public class ClientFactory
{
public Client1 getClient1(){return new Client1();}
public Client2 getClient2(){return new Client2();}
}
public class BaseClient
{
public Errors errors = null;
}
public class Client1 extends BaseClient
{
public void testClient1(){...}
}
public class Client2 extends BaseClient
{
public void testClient2()
{
//here i am directly passing the error object
//what is a better way?
//is there a more efficient way to make the SAME error object
//available to Client3
new Client3(this.errors).testClient3();
...
}
}
public class Client3 extends BaseClient
{
public Client3(Errors errors){this.errors = errors;}
public void testClient3(){...}
}
答案 0 :(得分:1)
当我想编写一个方法调用的短链时,我通常会使用lambda表达式,但我希望方法相对于任何类型的状态进行更改。至于你的场景,你的每个测试都是一个lambda表达式,这意味着我将testClient4方法传递给testClient3方法,testClient3方法传递给testClient2方法等等。但是,代码变得越来越丑陋您的方法调用链变长。
=>您可以使用Fluent接口:您可以让每个方法执行一些逻辑,然后返回一个实例,您可以在该实例上调用要执行的下一个内联方法。
显然,每个实例都需要引用下一个内联实例,知道它将调用的实例(Client1将引用Client2,Client2引用Client3等)。
这样可行,但在这种情况下,我不是粉丝!我说它比干净的编码更具诀窍。您应该单独使用每个客户端的流畅接口,除非您的某个方法实际上返回另一个实例:
client1.testClient1()。testClient2()。testClient3() 如果有充分的理由,每个测试方法返回下一个客户端的实例
但是在测试方法之间插入getClient方法是没有意义的......
答案 1 :(得分:0)
有没有办法链接不同类的实例?提供的示例是尝试连接属于不同类实例的方法失败。
client.getClient1().testClient1().getClient2().testClient2().assert(...);
为了链接这样的方法,每个方法必须返回一个对象的引用,该对象支持您要调用的方法。但是,每个测试方法都会返回void
。
在这种情况下,方法链接似乎非常值得怀疑,因为您在不同的类型上运行。像这样的链中的方法通常只是return this;
,因此可以在启动链的完全相同的对象上调用另一个方法。
此外,您的方法名称表明您正在尝试对代码进行一些自动化测试。您应该了解已建立的测试技术和库。特别是,JUnit通常用于Java和其他语言的变体。在诸如此类的框架中编写测试时,某些技术被认为是很好的做法。
要明确这一点,你当然不应该将测试代码与生产代码混合在一起。
此外,在同一示例中,Client2与Client3共享错误对象。什么是在子类和非关联类之间共享对象的更有效方法?
//here i am directly passing the error object
//what is a better way?
//is there a more efficient way to make the SAME error object
//available to Client3
new Client3(this.errors).testClient3();
将对象发送到类的唯一方法是将参数传递给构造函数或方法。这就是Java的工作原理。
请注意,由于您传递的是引用变量,因此开销很小。您没有复制整个对象。这意味着Client2
的当前实例和Client3
的新实例都引用了相同的错误对象。
答案 2 :(得分:0)
我并没有真正得到你真正需要的东西,但是在代码的实际状态下它甚至无法编译,因为你试图从"客户端" void方法返回的对象。
如果您不知道有多少客户端以及您将从哪种类型获得,我只需使用一个列表。
如果您想使用' testClient'来链接客户端。方法,然后首先这个方法应该返回下一个客户端(这是一种非常笨拙的方式链接对象),然后你应该开始使用更多的抽象和重写技术。
基本上,只要它是" BaseClient",就没有必要知道你正在处理什么对象,但如果你命名子方法" testClient1" ," testClient2"等等...你基本上打破它,你需要开始考虑你实际得到的东西,并相应地调整你的代码。
最后,这里不需要工厂,但如果你想要工厂,它应该是静态的。
这是一个有效的例子,我并不真正理解你想做什么,所以它可能无法解决你的问题,但它是一个有效的解决方案,以及#34;链接实例":
主要强>
public class Foo
{
// arguments are passed using the text field below this editor
public static void main(String[] args)
{
StubRunner stub = new StubRunner();
stub.run();
}
}
<强> Stubrunner:强>
public class StubRunner implements Runnable
{
public void run(){
Object clients = ClientFactory.getClient1();
while (null!= clients && clients instanceof BaseClient) {
clients = ((BaseClient) clients).test();
}
}
}
<强>基强>
public abstract class BaseClient
{
public Exception errors = null;
public BaseClient() {};
public BaseClient(Exception errors) {
this.errors = errors;
}
public abstract BaseClient test();
public void checkErrors() {
System.out.println(this.toString());
assert null == errors;
}
}
客户1:
public class Client1 extends BaseClient
{
public BaseClient test(){
checkErrors();
return new Client2();
}
}
客户2:
public class Client2 extends BaseClient
{
public BaseClient test()
{
checkErrors();
return new Client3(this.errors);
}
}
客户3:
public class Client3 extends BaseClient
{
public Client3(Exception errors) {
super(errors);
}
public BaseClient test() {
checkErrors();
return null;
}
}
<强>工厂:强>
公共最终类ClientFactory { private ClientFactory(){};
public static Client1 getClient1(){return new Client1();}
public static Client2 getClient2(){return new Client2();}
}
这输出以下内容:
test.Client1@15db9742 test.Client2@6d06d69c test.Client3@7852e922
答案 3 :(得分:0)
现在testClient1()
可以返回客户端工厂等。但这很复杂。
另一种监管语法是覆盖上下文提供类。
new ClientFactory() {{
getClient1().testClient1();
getClient2().testClient2().assert(...);
}};
这里的初始化块(&#34;匿名构造函数&#34;)将提供上下文。 然后,当testClient2返回Client2时,可以进行一些链接。
它可以是一个干净而有用的设计,例如我在sourceforge.net上的模糊语法分析器AnyParser(纯粹是一种精湛的工艺)。
答案 4 :(得分:0)
谢谢大家的帮助。您的建议使我能够达成以下工作解决方案。也许它不是最好的,所以寻求宝贵的时间和专业知识来指导更好的解决方案。
鉴于一些评论我的命名惯例是可疑的,我试图在一定程度上修改它们。请耐心等待。
目标是:
chain instances of different classes
share objects between subclasses and unassociated classes
问题描述:
<强> State.java 强>
public class State {
public Boolean ISAUDITED = false;
public int ERRORCODE = 0;
public String ERRORTEXT = "";
public void raise(int code, String msg){
this.ERRORCODE = code;
this.ERRORTEXT = msg;
}
}
<强> BaseClient.java 强>
public abstract class BaseClient {
public State state;
public BaseClient(){
this.state = new State();
}
public BaseClient(State state){
this.state = state;
}
public ClientFactory getTest(){
return new ClientFactory(state);
}
public Boolean Assert(){
if(state.ERRORCODE == 0){
System.out.println("Parsing was successful.");
return true;
}
else{
System.out.println("Parsing was not successful.");
return false;
}
}
public abstract BaseClient GoTo();
}
<强> Task1.java 强>
public class Task1 extends BaseClient {
public Task1(){ GoTo(); }
public Task1(State state){ super(state); GoTo(); }
public Task1 performTask1(){
if(!state.ISAUDITED)
{
System.out.println("perform Task1");
state.ISAUDITED = true;
}
return this;
}
@Override
public BaseClient GoTo() {
if(state.ISAUDITED){
new Task2(state).performTask2();
}
return this;
}
}
<强> Task2.java 强>
public class Task2 extends BaseClient{
public Task2(){ GoTo(); }
public Task2(State state){ super(state); GoTo(); }
public Task2 performTask2(){
if(state.ISAUDITED)
{
System.out.println("perform Task2");
state.ISAUDITED = false;
}
return this;
}
@Override
public BaseClient GoTo() {
if(!state.ISAUDITED){
new Task1().performTask1();
}
return this;
}
}
<强> Task3.java 强>
public class Task3 extends BaseClient {
public Task3(){ }
public Task3(State state){ super(state); }
public Task3 GoTo(){
if(!state.ISAUDITED) {new Task1(state).performTask1();}
System.out.println("Opening Task3");
return this;
}
public Task3 performTask3(){
try
{
this.GoTo();
System.out.println("Submitted Task3 Data");
}
catch(Exception e){
state.raise(1, e.getMessage());
}
return this;
}
public Task3 performMixedTasks(){
new Task4(state).performTask4();
this.performTask3();
return this;
}
}
<强> Task4.java 强>
public class Task4 extends BaseClient {
public Task4(){ }
public Task4(State state){ super(state); }
public Task4 GoTo(){
if(!state.ISAUDITED) {new Task1(state).performTask1();}
System.out.println("Opening Task 4");
return this;
}
public Task4 performTask4(){
try
{
this.GoTo();
System.out.println("Submitted Task 4 Data");
}
catch(Exception e){
state.raise(1, e.getMessage());
}
return this;
}
}
<强> ClientFactory.java 强>
public class ClientFactory {
State state;
public ClientFactory(){
state = new State();
}
public ClientFactory(State state){
this.state = state;
}
public Task3 loadTask3(){return new Task3(state);}
public Task4 loadTask4(){return new Task4(state);}
}
<强> StubRunner1.java 强>
public class StubRunner1 {
public static void main(String[] arg)
{
ClientFactory test = new ClientFactory();
test.loadTask3()
.performTask3()
.getTest()
.loadTask4()
.performTask4()
.Assert();
}
}
**RESULT IS**
perform Task1
Opening Task3
Submitted Task3 Data
Opening Task4
Submitted Task4 Data
Parsing was successful.
<强> StubRunner2.java 强>
public class StubRunner2 {
public static void main(String[] args) {
ClientFactory test = new ClientFactory();
test.loadTask3()
.performMixedTasks()
.Assert();
}
}
**RESULT IS**
perform Task1
Opening Task4
Submitted Task4 Data
Opening Task3
Submitted Task3 Data
Parsing was successful.