I thought I would learn a design pattern today and picked this one. I wrote a simple Android test demo to test the pattern.
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<Spinner
android:id="@+id/select"
android:layout_height="wrap_content"
android:layout_width="fill_parent" />
<EditText
android:id="@+id/editOne"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="First"
android:editable="false"/>
<EditText
android:id="@+id/editTwo"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Second"
android:editable="false"/>
</LinearLayout>
strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">TestingStrategyPattern</string>
<string-array name="names">
<item>Queued</item>
<item>In Progress</item>
<item>Started</item>
<item>Finished</item>
<item>Destroyed</item>
<item>Bombarded</item>
<item>Ready</item>
<item>Paused</item>
<item>Stopped</item>
<item>Resolved</item>
<item>Abandoned</item>
</string-array>
</resources>
MyActivity.java
package com.example.TestingStrategyPattern;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.Spinner;
public class MyActivity extends Activity {
private boolean editOneEnabled = false;
private boolean editTwoEnabled = false;
/**
* Called when the activity is first created.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Spinner statesSpinner = (Spinner) findViewById(R.id.select);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, R.array.names, android.R.layout.simple_spinner_dropdown_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
statesSpinner.setAdapter(adapter);
final EditText editOne = (EditText) findViewById(R.id.editOne);
final EditText editTwo = (EditText) findViewById(R.id.editTwo);
statesSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String selectedItem = parent.getSelectedItem().toString();
if(selectedItem.equals("Queued")) {
editOneEnabled = true;
editTwoEnabled = false;
} else if(selectedItem.equals("In Progress")){
editOneEnabled = true;
editTwoEnabled = false;
} else if(selectedItem.equals("Started")) {
editOneEnabled = true;
editTwoEnabled = false;
} else if(selectedItem.equals("Bombarded")) {
editOneEnabled = true;
editTwoEnabled = false;
} else if(selectedItem.equals("Ready")) {
editOneEnabled = false;
editTwoEnabled = true;
} else if(selectedItem.equals("Paused")) {
editOneEnabled = false;
editTwoEnabled = true;
} else if(selectedItem.equals("Stopped")) {
editOneEnabled = false;
editTwoEnabled = true;
} else if(selectedItem.equals("Resolved")) {
editOneEnabled = false;
editTwoEnabled = true;
} else if(selectedItem.equals("Abandoned")) {
editOneEnabled = true;
editTwoEnabled = false;
} else {
editOneEnabled = false;
editTwoEnabled = false;
}
if(editOneEnabled == true) {
editOne.setEnabled(true);
} else {
editOne.setEnabled(false);
}
if(editTwoEnabled == true) {
editTwo.setEnabled(true);
} else {
editTwo.setEnabled(false);
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
}
Now this is the code before I refactored it to use the strategy pattern, but effectively what happens is that based on the selection from the drop down/spinner widget, the two text fields will get enabled or disabled accordingly.
Here is the refactored code:
Strategy.java
package com.example.strategy;
public interface Strategy {
boolean isEnabled(String state);
}
Context.java
package com.example.strategy;
public class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public boolean executeStrategy(String state) {
return this.strategy.isEnabled(state);
}
}
ButtonOneStrategy.java
package com.example.strategy;
import java.util.HashMap;
import java.util.Map;
public class ButtonOneStrategy implements Strategy {
private Map<String, Boolean> mappings;
public ButtonOneStrategy() {
mappings = new HashMap<String, Boolean>();
mappings.put("Queued", true);
mappings.put("In Progress", true);
mappings.put("Started", true);
mappings.put("Bombarded", true);
mappings.put("Ready", false);
mappings.put("Paused", false);
mappings.put("Stopped", false);
mappings.put("Resolved", false);
mappings.put("Abandoned", false);
mappings.put("Destroyed", false);
mappings.put("Finished", false);
}
@Override
public boolean isEnabled(String state) {
return mappings.get(state);
}
}
ButtonTwoStrategy.java
package com.example.strategy;
import java.util.HashMap;
import java.util.Map;
public class ButtonTwoStrategy implements Strategy {
private Map<String, Boolean> mappings;
public ButtonTwoStrategy() {
mappings = new HashMap<String, Boolean>();
mappings.put("Queued", false);
mappings.put("In Progress", false);
mappings.put("Started", false);
mappings.put("Bombarded", false);
mappings.put("Ready", true);
mappings.put("Paused", true);
mappings.put("Stopped", true);
mappings.put("Resolved", true);
mappings.put("Abandoned", true);
mappings.put("Destroyed", false);
mappings.put("Finished", false);
}
@Override
public boolean isEnabled(String state) {
return mappings.get(state);
}
}
MyActivity.java
package com.example.TestingStrategyPattern;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.Spinner;
import com.example.strategy.ButtonOneStrategy;
import com.example.strategy.ButtonTwoStrategy;
import com.example.strategy.Context;
public class MyActivity extends Activity {
private boolean editOneEnabled = false;
private boolean editTwoEnabled = false;
/**
* Called when the activity is first created.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Spinner statesSpinner = (Spinner) findViewById(R.id.select);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, R.array.names, android.R.layout.simple_spinner_dropdown_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
statesSpinner.setAdapter(adapter);
final EditText editOne = (EditText) findViewById(R.id.editOne);
final EditText editTwo = (EditText) findViewById(R.id.editTwo);
final com.example.strategy.Context btnOneContext = new Context(new ButtonOneStrategy());
final com.example.strategy.Context btnTwoContext = new Context(new ButtonTwoStrategy());
statesSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String selectedItem = parent.getSelectedItem().toString();
editOneEnabled = btnOneContext.executeStrategy(selectedItem);
editTwoEnabled = btnTwoContext.executeStrategy(selectedItem);
if(editOneEnabled == true) {
editOne.setEnabled(true);
} else {
editOne.setEnabled(false);
}
if(editTwoEnabled == true) {
editTwo.setEnabled(true);
} else {
editTwo.setEnabled(false);
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
}
I added Strategy.java, Context.java, ButtonOneEnabled.java, ButtonTwoEnabled.java and changed MyActivity.java as a result of the new pattern.
Here are my questions:
- What do you think about how I went about implementing this pattern? Have I done it in a good way?
- I felt that this pattern was overkill for the example. Could someone explain the benefits of using this pattern in larger examples or indeed in this example? I really felt that although this pattern could scale really well, it felt a bit of an over design, creating more objects with their own maps etc. I thought it was too heavy. What do you think about this?