is this a design problem?

G

gerrymcc

Hello, I hope it's okay to post to the three groups simultaneously.
I've got a set of four applets, all of which use the same GUI,
except for one change. I want to reuse the 100+ lines of setup code
for the GUI, but can't seem to do that because of the single line that

changes. Cutting and pasting the redundant code works, but it's a
pretty dull solution.
The idea of the following is that I have an Answer class (subclass of
Panel) called studentWork. studentWork contains an array of
EditableMeasure types (which are Canvas subclasses). In applet Two I
have a mix of EditableMeasures and EditableMeasureTypeTwos, in applet
Three I have a mix of EditableMeasures and EditableMeasureTypeThrees,
etc. This is the only change to the GUI, and have had to make the
single change in init() each time - studentWork = new Answer(this,
selectedMode); or studentWork = new AnswerType2(this, selectedMode);
or new AnswerType3( etc). The code below doesn't work, I guess
because the call to super.init() must use the setStudentWork() from
class One, rather than the definition I want, in class Two.
Is there any way the code from init() and itemStateChanged can be
reused and still create the relevant type of studentWork?

Thanks for any help,
Gerard

import java.awt.event.*;
import java.awt.*;
import java.applet.*;

public class One extends Applet implements ActionListener,
ItemListener{

Answer studentWork;
Panel workArea;
int [] selectedMode;

public void init() {
setStudentWork();
// 100+ lines of gui setup follows
workArea = new Panel();
workArea.add( studentWork);
}

void setStudentWork(){
studentWork = new Answer( this, selectedMode);
}

public void itemStateChanged( ItemEvent ie){
switch( modeChoice.getSelectedIndex()){
case 0: selectedMode = aChoice;
break;
. ...
}
setStudentWork();
workArea.add(studentWork);
}

public void actionPerformed( ActionEvent e){...}
}

class EditableMeasure extends Canvas implements MouseListener,
MouseMotionListener{
// hundreds of lines
}

class Answer extends Panel{
public EditableMeasure [] bar;

public Answer() {}
public Answer(One a, int [] part){
setLayout( new FlowLayout( FlowLayout.LEFT,0,0));
bar = new EditableMeasure[ part.length];
for( int i = 0; i<part.length; i++){
if( i == 0)
bar = new EditableMeasure( a, 1);
else if( i == part.length - 1)
bar = new EditableMeasure( a, 2);
else
bar = new EditableMeasure( a);

add( bar);
}
}
}

class Two extends One{
public void init(){
super.init();
}
void setStudentWork(){
studentWork = new AnswerType2( this, selectedMode);
}
}

class EditableMeasureType2 extends Canvas etc{}

class AnswerType2 extends Answer{
public AnswerType2 (Two a, int [] part){
setLayout( new FlowLayout( FlowLayout.LEFT,0,0));
bar = new EditableMeasure[ part.length];
for( int i = 0; i<part.length; i++){
if( i == 0)
bar = new EditableMeasureType2( a, 1);
else if( i == part.length - 1)
bar = new EditableMeasure( a, 2);
else
bar = new EditableMeasureType2( a);
add( bar);
}
}
}
 
J

John C. Bollinger

Hello, I hope it's okay to post to the three groups simultaneously.

No, not really. [CLJ removed because it doesn't exist; followups
directed to CLJP.]
I've got a set of four applets, all of which use the same GUI,
except for one change. I want to reuse the 100+ lines of setup code
for the GUI, but can't seem to do that because of the single line that

changes. Cutting and pasting the redundant code works, but it's a
pretty dull solution.

You seem to be on the right track with your code below. It should not
be necessary to implement a copy & paste solution, and such a thing will
greatly increase your maintenance burden (if this is code you will need
to maintain).
The idea of the following is that I have an Answer class (subclass of
Panel) called studentWork.

Being a bit pedantic here, no, that's not what you have. You have a
reference-type variable named studentWork that can hold a reference to
an Answer.
studentWork contains an array of
EditableMeasure types (which are Canvas subclasses). In applet Two I
have a mix of EditableMeasures and EditableMeasureTypeTwos, in applet
Three I have a mix of EditableMeasures and EditableMeasureTypeThrees,
etc.

Continuing with the pedantry, in different applets studentWork contains
references to objects of different subclasses of Answer, or of class
Answer itself. This is perfectly acceptable, and the details of the
differences between the various classes are immaterial.
This is the only change to the GUI, and have had to make the
single change in init() each time - studentWork = new Answer(this,
selectedMode); or studentWork = new AnswerType2(this, selectedMode);
or new AnswerType3( etc). The code below doesn't work, I guess
because the call to super.init() must use the setStudentWork() from
class One, rather than the definition I want, in class Two.

What do you mean it "doesn't work." Do you get a compile-time error?
Does it compile and run but not do what you expect?

I very much doubt whether the invocation by Two.init() of its
super.init() causes any kind of runtime problem, but if that's all that
Two.init() needs to do then it is better to just let Two inherit its
superclass' init() method.

There is some chance that you are running into problems related to these
applets' packages -- you would be well advised to assign them and their
associated classes to a package other than the default package. (The
way the example code is written, One and Two will need to be in the same
package.)

It is also possible that you are running into problems related to the
physical packaging of the classes. The classloader that loads Two will
need to also be able to load One, which probably means that both classes
should be in the same jar or in the same directory.
Is there any way the code from init() and itemStateChanged can be
reused and still create the relevant type of studentWork?

As I said before, you appear to be going about it in a reasonable way.
We can be more help to you if you give us the details of the actual
problems you are experiencing.


John Bollinger
(e-mail address removed)
import java.awt.event.*;
import java.awt.*;
import java.applet.*;

public class One extends Applet implements ActionListener,
ItemListener{

Answer studentWork;
Panel workArea;
int [] selectedMode;

public void init() {
setStudentWork();
// 100+ lines of gui setup follows
workArea = new Panel();
workArea.add( studentWork);
}

void setStudentWork(){
studentWork = new Answer( this, selectedMode);
}

public void itemStateChanged( ItemEvent ie){
switch( modeChoice.getSelectedIndex()){
case 0: selectedMode = aChoice;
break;
...
}
setStudentWork();
workArea.add(studentWork);
}

public void actionPerformed( ActionEvent e){...}
}

class EditableMeasure extends Canvas implements MouseListener,
MouseMotionListener{
// hundreds of lines
}

class Answer extends Panel{
public EditableMeasure [] bar;

public Answer() {}
public Answer(One a, int [] part){
setLayout( new FlowLayout( FlowLayout.LEFT,0,0));
bar = new EditableMeasure[ part.length];
for( int i = 0; i<part.length; i++){
if( i == 0)
bar = new EditableMeasure( a, 1);
else if( i == part.length - 1)
bar = new EditableMeasure( a, 2);
else
bar = new EditableMeasure( a);

add( bar);
}
}
}

class Two extends One{
public void init(){
super.init();
}
void setStudentWork(){
studentWork = new AnswerType2( this, selectedMode);
}
}

class EditableMeasureType2 extends Canvas etc{}

class AnswerType2 extends Answer{
public AnswerType2 (Two a, int [] part){
setLayout( new FlowLayout( FlowLayout.LEFT,0,0));
bar = new EditableMeasure[ part.length];
for( int i = 0; i<part.length; i++){
if( i == 0)
bar = new EditableMeasureType2( a, 1);
else if( i == part.length - 1)
bar = new EditableMeasure( a, 2);
else
bar = new EditableMeasureType2( a);
add( bar);
}
}
}
 
H

Harald Hein

Hello, I hope it's okay to post to the three groups
simultaneously.

One would have been enough.
I've got a set of four applets, all of which use
the same GUI, except for one change. I want to reuse the 100+
lines of setup code for the GUI, but can't seem to do that because
of the single line that

changes.

A common structure to solve such problems looks like this:

class Base {
public void method() {
// Do first part of common code here

// For specific parts that have to be different
// call a method
result = special(arguments);

// Continue with the common code
}


// Provide a default implementation for the special
// method. Either leave it empty, or implement the
// most common behavior.
protected someResultClass special(arguments) {
// do the most common thing
return aResult;
}
}

// Implement a subclass for the behavior that deviates
// from the common behavior. All you have to do is to
// override the special() method
class Derived extends Base {
protected someResultClass special(argument) {
// do something different here
return anotherResult;
}
}


If you need the normal behavior use the base class:

Base c = new Base();

If you need the special behavior use something like

Base c = new Derived();

instead. Note that Base is used as the type for the varible in both
cases. This allows client code to work independent of the actual
version of special() that is used.

If you need even more different versions, implement more subclasses of
Base.
 
D

Douwe

Hello, I hope it's okay to post to the three groups simultaneously.
I've got a set of four applets, all of which use the same GUI,
except for one change. I want to reuse the 100+ lines of setup code
for the GUI, but can't seem to do that because of the single line that

changes. Cutting and pasting the redundant code works, but it's a
pretty dull solution.
The idea of the following is that I have an Answer class (subclass of
Panel) called studentWork. studentWork contains an array of
EditableMeasure types (which are Canvas subclasses). In applet Two I
have a mix of EditableMeasures and EditableMeasureTypeTwos, in applet
Three I have a mix of EditableMeasures and EditableMeasureTypeThrees,
etc. This is the only change to the GUI, and have had to make the
single change in init() each time - studentWork = new Answer(this,
selectedMode); or studentWork = new AnswerType2(this, selectedMode);
or new AnswerType3( etc). The code below doesn't work, I guess
because the call to super.init() must use the setStudentWork() from
class One, rather than the definition I want, in class Two.
Is there any way the code from init() and itemStateChanged can be
reused and still create the relevant type of studentWork?

Thanks for any help,
Gerard

import java.awt.event.*;
import java.awt.*;
import java.applet.*;

public class One extends Applet implements ActionListener,
ItemListener{

Answer studentWork;
Panel workArea;
int [] selectedMode;

public void init() {
setStudentWork();
// 100+ lines of gui setup follows
workArea = new Panel();
workArea.add( studentWork);
}

void setStudentWork(){
studentWork = new Answer( this, selectedMode);
}

public void itemStateChanged( ItemEvent ie){
switch( modeChoice.getSelectedIndex()){
case 0: selectedMode = aChoice;
break;
. ...
}
setStudentWork();
workArea.add(studentWork);
}

public void actionPerformed( ActionEvent e){...}
}

class EditableMeasure extends Canvas implements MouseListener,
MouseMotionListener{
// hundreds of lines
}

class Answer extends Panel{
public EditableMeasure [] bar;

public Answer() {}
public Answer(One a, int [] part){
setLayout( new FlowLayout( FlowLayout.LEFT,0,0));
bar = new EditableMeasure[ part.length];
for( int i = 0; i<part.length; i++){
if( i == 0)
bar = new EditableMeasure( a, 1);
else if( i == part.length - 1)
bar = new EditableMeasure( a, 2);
else
bar = new EditableMeasure( a);

add( bar);
}
}
}

class Two extends One{
public void init(){
super.init();
}
void setStudentWork(){
studentWork = new AnswerType2( this, selectedMode);
}
}

class EditableMeasureType2 extends Canvas etc{}

class AnswerType2 extends Answer{
public AnswerType2 (Two a, int [] part){
setLayout( new FlowLayout( FlowLayout.LEFT,0,0));
bar = new EditableMeasure[ part.length];
for( int i = 0; i<part.length; i++){
if( i == 0)
bar = new EditableMeasureType2( a, 1);
else if( i == part.length - 1)
bar = new EditableMeasure( a, 2);
else
bar = new EditableMeasureType2( a);
add( bar);
}
}
}


I don´t see any difference in the classes AnswerType2 and AnswerType
accept that AnswerType uses one time the EditableMeasure instead of
EditableMeasureType2. But I don´t see any differences in
EditableMeasure and EditableMeasureType2. So in both cases keep it
with one Class. Also the applets do not differ much. I´ve rewritten
the code partialy .. I can probably increase the code its quality even
more but for that I need the complete code. Note that
createEditableMease returns just a canvas and that I have changed the
first parameter of the constructor of Answer to Applet. I´ve also
rewritten your bar[] array fill loop ... always try to move as much as
possible code outside the loop since this increases performance (which
in this case is not really a problem but anyway)

Here is the code. I didn´t check it on typos :|

import java.awt.event.*;
import java.awt.*;
import java.applet.*;

public abstract class StudentApplet extends Applet implements
ActionListener, ItemListener {

Answer studentWork;
Panel workArea;
int [] selectedMode;

public void init() {
setStudentWork();
// 100+ lines of gui setup follows
workArea = new Panel();
workArea.add( studentWork);
}

void abstract setStudentWork();

public void itemStateChanged(ItemEvent ie){
switch( modeChoice.getSelectedIndex()){
case 0: selectedMode = aChoice;
break;
. ...
}
setStudentWork();
workArea.add(studentWork);
}

public void actionPerformed( ActionEvent e){...}
}

public class One extends StudentApplet() {
void setStudentWork() {
studentWork = new AnswerType1(this, selectedMode);
}
}


public class Two extends StudentApplet() {
void setStudentWork() {
studentWork = new AnswerType2(this, selectedMode);
}
}






class abstract AbstractAnswer extends Panel {
public EditableMeasure [] bar;

public Answer() {}
public Answer(Applet a, int part[]){
setLayout(new FlowLayout(FlowLayout.LEFT,0,0));
bar = new EditableMeasure[part.length];

int i = 0;
bar = createEditableMease( a, 1);

for(; i<part.length-1; i++){
bar = createEditableMease( a, -1);
}
bar = createEditableMease( a, 2);
}

public Canvas createEditableMease(Applet a, int val) {
Canvas result = createEditableMeaseImpl(a, val);
add(result);
return result;
}

public abstract Canvas createEditableMeaseImpl(Applet a, int val);

}


class AnswerType1 extends AbstractAnswer {
public Canvas createEditableMeaseImpl(Applet a, int val) {
if (val == -1)
return new EditableMeasureType1(a);
return new EditableMeasureType1(a, val);
}

}

class AnswerType2 extends AbstractAnswer {
public Canvas createEditableMeaseImpl(Applet a, int val) {
if (val == -1)
return new EditableMeasureType2(a);
return new EditableMeasureType2(a, val);
}

}







class EditableMeasureType1 extends Canvas implements MouseListener,
MouseMotionListener {

// hundreds of lines
}

class EditableMeasureType2 extends Canvas etc{}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top