Sequence Strategy
For this assignment you will add code to an existing program which illustrates the strategy design pattern. As defined on this page, to use the strategy pattern we do the following:
- Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from the clients that use it.
- Capture the abstraction in an interface, bury implementation details in derived classes.
The Sequence
Class
The Sequence
class is the “client” in the definition above. This is a flexible class that can be used to generate sequences of numbers in different ways. With a Sequence
object you can get the next item in the sequence, get the current position in the sequence, and seek to a new position in the sequence. The class stores the numbers that have been generated so far in a list so that it can re-use those numbers after seeking backwards, but new numbers are generated when continually calling get_next()
past the point where the sequence has been generated so far.
This class could be useful in a number of different programs. For example, in a video game you might generate a level in a random fashion, so you may need an unbounded sequence of random numbers. If the player dies in the level, you could re-use the same sequence of random numbers when they try again by seeking back to the beginning of the sequence. After seeking to the beginning, you will get the same sequence of numbers as you did before, and if the player gets farther in the level it will continue to generate more new numbers.
With this class, you can generate more than random numbers in a sequence, you just have to use a different generator for the numbers.
Abstract Base Class ItemGenerator
We want to have different kinds of Sequence
objects which generate different kids of sequences. The only thing that differs among these different kinds of Sequence
objects is the generator from which they get their numbers.
To accomplish this I created an ItemGenerator
abstract base class which has a single method, get_next()
. The Sequence
class takes a ItemGenerator
object in its initializer, stores it as an attribute, and uses this generator to get the values for the sequence. ItemGenerator
is the abstract interface in the Strategy definition above.
We can say that a Sequence
is composed of an ItemGenerator
. Or that a Sequence
has an ItemGenerator
. We are leveraging polymorphism because we can pass in any concrete (non-abstract) ItemGenerator
object to the Sequence
constructor.
Here our family of algorithms are item generators. They are all interchangeable because they have all extend the same abstract base class (ItemGenerator
), and thus have the same interface. The client using these algorithms is the Sequence
class. We can create new kinds of sequence objects without changing the code of the Sequence
class at all, we simply pass a different ItemGenerator
object to the constructor to get different behavior.
From the perspective of the Sequence
class, the implementation details of each separate number generator are irrelevant. As long as a Sequence
object can call get_next()
on the generator it is happy.
Existing Code
In sequence.py
there are already two concrete implementations of ItemGenerator
called OrderedIntGenerator
and RandomIntGenerator
. OrderedIntGenerator
generates the sequence of increasing non-negative integers starting with 0 (0, 1, 2, 3, …). RandomIntGenerator
generates a random sequence of integers within a given range.
Examine the Sequence
class and the ItemGenerator
classes and be sure you understand what is going on. You may want to read these instructions multiple times once you have looked at the code! For this assignment, understanding the relationships between these classes is as important as the code you will add.
main.py
contains code to test sequences. If you run main.py
you will be presented with an interactive testing environment where you can try out sequences with the two existing generators. Play around with this a little so that you see what is going on with the sequences.
New ItemGenerator
Class
Your task for this assignment is to create one more class in sequence.py
named FromListGenerator
. This class must extend ItemGenerator
. Additionally you will add an object from your class to the generators
list in main()
so that you can test it with the interactive testing environment.
FromListGenerator
The FromListGenerator
draws its numbers from a list, in order. Once all the numbers from the list have been used, it starts over from the beginning. So if we construct the object like this:
and we pass this object to the initializer of a Sequence
, then the sequence generated will look like this:
1, 2, 3, 1, 2, 3, 1, ...
You will need to keep track of the current position in the list as an attribute and update it accordingly when new items are generated.
There is a commented out line in the generators
list in main()
that adds a FromListGenerator
object to the test list. Uncomment this line after you have created your class, and import FromListGenerator
from the sequence
module. Then re-run main.py
so you can test your class.
Submission
Test your class to make sure it works and then push your submission. For full credit on this assignment your code must pass all the tests and be PEP 8 complient.
For the git-keeper tests on this assignment I used the pytest
testing framework. If the tests fail you will see some assertion errors. If it is unclear what went wrong let me know.