/*
 * This File is one of the examples from Java Object Oriented Programming
 * Do not reproduce this code for others or use it in a commercial setting without prior permission from the author.
 */
package salesApplication;

import datasource.DataSource;
import datasource.FileDataSource;
import datasource.DataSourceFactory;
import datasource.InMemoryDataSource;
import datasource.SingletonDataSource;
import java.util.List;
import products.Colour;
import products.Item;
import products.Product;

/**
 *
 * @author Matthew Gregory
 * @website www.matthewgregory-author.com.au
 *
 */
public class TestPatterns {

    public static void main(String[] args) {
       
        //Factory Pattern
        //Consider the following code
//        DataSource ds = new FileDataSource();
        //As a user we don't care (or don't want to know)
        //what specific class we need to create in order to 
        //implement our datasource.
        //Let the factory take care of which class should implement it.
        //then we don't have to worry.
        //In addition if at some stage we change the implementation
        //we want clinets to use all we have to do is change the code 
        //in the factory and not every single piece of code that uses it!
        //Get an instance of the factory.
//        DataSourceFactory dsf = new DataSourceFactory();
        //Use the factory to give me a datasource 
        //I don't care what class implements it, I don't even want to know
//        DataSource ds = dsf.getDataSource();
//        ds.retrieveList("Demo").printList();

        //I can even modify my factory so that if I want to request
        //a specific type of datasource I can.
        //For example add a method to the factory
        //called getDataSourceFrom() that let's me pas the type
        //of datasource I am after (as a String).
        //Use the factory to get the datasource we want
//        DataSource ds = dsf.getDataSourceFrom("File");
//        ds.retrieveList("Demo").printList();
        //You could even have a method that returns a default
        //datasource for clients who don't care which implementation to use.
        
        //Singleton Pattern
        //Another pattern is called the Singleton pattern and is used
        //when we only want a single instance that everyone uses.
        //this will save on memeory and also means that the data can be shared
        //Again we can use the DataSource as an example.  We only want one
        //copy of the datasource for everyone, and if someone adds 
        //to the datasource everyone else should be able to see it.
        //To test this let's create two data sources then add a 
        //price list to one of our datasource, print the names from both
        //data sources and see that it's only in the one we added it to.
//        DataSource ds1 = new InMemoryDataSource();
//        DataSource ds2 = new InMemoryDataSource();
//        ds1.saveList("Empty List", new PriceList());
//        ds1.getListNames();
//        ds2.getListNames();
        //Create a class called SingletonDataSource that stores an
        //instance of InMemoryDataSource and has a static method called getInstance 
        //that checks to see if the instance has already been created.
        //if it has then it should return that instance, otherwise it
        //should create a new instance of FileDataSource and return that.
        //Use this singleton class to create two 'instances' of the datasource
//        DataSource ds1 = SingletonDataSource.getInstance();
//        DataSource ds2 = SingletonDataSource.getInstance();
//        ds1.saveList("Empty List", new PriceList());
//        ds1.getListNames();
//        ds2.getListNames();
        
        //Builder Pattern
        //The idea of this pattern is that we want a way of consturcting
        //an object without being restricted by the order and number of
        //fileds in the object.  In other words, we don't want to use a 
        //construtor to build or object as this gives us only a 
        //limited number of options, and you have to know the 
        //correct number and order of the parameters that they require.
        //instead we will offer methods to specify whichever fields
        //I want to provide values for and be able to call them in
        //any order.  An example of this kind of pattern can be seen
        //in Dates in the java.time package.
        //In the Product class a whole set of new methods has been define
        //for you.  Notice that the first one is a static method that constructs an Product with a
        //given name, and the rest (with a prefix of 'at') set the various 
        //fields of a product and then reutrn that product ready 
        //for a call to the next method to set another field
        //Once you have an idea of the code you need to write to 
        //implement a builder pattern construct a product using the 
        //methods provided.
//        Product p = Product.of("New Product")
//                           .atPrice(3.45)
//                           .atDescription("A brand new product.")
//                           .atBrand("Gregco")
//                           .atColour(Colour.GREEN);
//        p.printProduct();
//        System.out.println("Other properties: \n"
//                           +"Brand - "+p.getBrand()+"\n"
//                           +"Colour - "+p.getColour());
        //Try doing this in a different order and commenting out
        //different fields!  Whatever you do it still works as long
        //as you create the product (i.e. include the of() method).
    }
}
