DesignPattern : Factory

1. Why should we use Factory Method?

    1) We want to control the way we create new instance of a certain class. We cannot merely use the new XXX() to create an instance.

    2) We want to keep our system robust and extensiable when we apply custom instaintiation of a certain class.

2. A simple example for explain Simple Factory Method:

    1) In a system we want to control the way we create a new vechicle.

        1) We want to apply permission check before we create new vehicle.

        2) We want to keep our vehicle number in a certain range. (Think of connection pool in JDBC)

        3) We want to keep our system extensiable and don't have to change code when we create a new kind of vehicle.

    2) The class diagram is as below.

        1) We extract the common attribute of Car and Plane as Movable.

            And create an interface Movable. Whenever we want to create another kind of Vehicle, we just implements Movable.

        2) We extract the common attribute of CarFactory and PlaneFactroy as VehicleFactory.

            And create an interface VehicleFactory. Whenever we want to apply a new kind of Vehicle generation process, we just implements VehicleFactory.

        3) We control the process of create a certain kind of Movable/Vehicle in its corrosponding VehicleFactory.

     3) Test case is as below. We can keep the code "new PlaneFactory()" in our config file.

package edu.xmu.designPattern.DesignPattern_Factory;

import org.junit.Test;

public class FactoryTest
{
	@Test
	public void testFactory()
	{
		VehicleFactory factory = new PlaneFactory();
		// VehicleFactory factory = new CarFactory();
		// VehicleFactory factory = new BroomFactory();
		Movable plane = factory.create();
		plane.move();
	}
}

  

3. How often Factory Method is used?

    1) We can take a look at JDK code.

        Whenever we encounter a method named getInstance(), then we can be sure that Factory Method is used to control the process of new instance generation.

        We cannot be sure whether a Singleton or a Multiton is used in the process. So we can be sure that Factory is more general aspect of instance generation than singleton.

        Singleton is only a typical kind of new instance generation. Factory method is the new instance generation process control.

    2) There are a lot of Factories in JDK.

        EG. KeyFactory, CertificateFactory... Because some kind of class is not appropriate to use the syntax of new XXX() to create an instance.

4. A simple for Abstract Factory Method

    1) What if a man is driving a car with a gun in his arm and an apple in his mouth. How can we create this man?

    2) Simply speaking, what if we want to create an instance of class that is associated with a series of other classes?

        What if we want to create a factory that can generate a series of instances of different classes?

    ---------- Example of creating without using Factory Method

package edu.xmu.designPattern.DesignPattern_Factory;

import org.junit.Test;

public class FactoryTest
{
	@Test
	public void testFactory()
	{
		Car car = new Car();
		AK47 ak47 = new AK47();
		Apple apple = new Apple();
		ak47.shoot();
		apple.printName();
		car.move();
	}
}

   -------- Example of creating with Factory Method

   1. Factory (Here we can control the process of new instance)

package edu.xmu.designPattern.DesignPattern_Factory;

public class DefaultFactory
{
	public Car createCar()
	{
		return new Car();
	}

	public AK47 createAK47()
	{
		return new AK47();
	}

	public Apple createApple()
	{
		return new Apple();
	}
}

   2. Test case

package edu.xmu.designPattern.DesignPattern_Factory;

import org.junit.Test;

public class FactoryTest
{
	@Test
	public void testFactory()
	{
		DefaultFactory defaultFactory = new DefaultFactory();
		Car car = defaultFactory.createCar();
		AK47 ak47 = defaultFactory.createAK47();
		Apple apple = defaultFactory.createApple();
		ak47.shoot();
		apple.printName();
		car.move();
	}
}

    But this factory is not extensiable/robust.

    What if we want to create a man that lives in magic world whose vehicle is broom instead of car, weapon is magic stick instead of AK47 and food is mushroom instead of apple?

    -------- Factory

package edu.xmu.designPattern.DesignPattern_Factory;

public class MagicFactory
{
	public Mushroom createMushroom()
	{
		return new Mushroom();
	}

	public MagicStick createMagicStick()
	{
		return new MagicStick();
	}
	
	public MagicBroom createMagicBroom()
	{
		return new MagicBroom();
	}
	
}

    -------- Test case (Here we have to totally change the previous code. This means the design is not extensiable)

package edu.xmu.designPattern.DesignPattern_Factory;

import org.junit.Test;

public class FactoryTest
{
	@Test
	public void testFactory()
	{
		// DefaultFactory defaultFactory = new DefaultFactory();
		// Car car = defaultFactory.createCar();
		// AK47 ak47 = defaultFactory.createAK47();
		// Apple apple = defaultFactory.createApple();
		// ak47.shoot();
		// apple.printName();
		// car.move();

		MagicFactory magicFactory = new MagicFactory();
		MagicBroom magicBroom = magicFactory.createMagicBroom();
		MagicStick magicStick = magicFactory.createMagicStick();
		Mushroom mushroom = magicFactory.createMushroom();

		// ...
	}
}

    How can we figure out a way that we don't have to change the code of using these factories?

    1) We can make the method name the same. So it is better we create an interface for these factories.

    2) We can make the way of generating object inside the factory the same name.

 

        3) Test case

package edu.xmu.designPattern.DesignPattern_Factory;

import org.junit.Test;

public class FactoryTest
{
	@Test
	public void testFactory()
	{
		AbstractFactory factory = new MagicFactory();
		// AbstractFactory factory = new DefaultFactory();

		Vehicle vehicle = factory.createVehicle();
		Weapon weapon = factory.createWeapon();
		Food food = factory.createFood();

		vehicle.run();
		weapon.shoot();
		food.printName();
	}
}

    Here we can easily switch the factory from real world to magic world.

    We can even move the code "new MagicFartory()" into config file. So now the code is simply extensiable.

    Whenever we want to make a new kind of world/factory, we just simply extends AbstractFactory. And the objects inside the world shold extends either Food, Weapon, Vehicle...

    And we merely change the config file. Then we can switch to the new world.

5. Comparision of two Factory

    1) We can think of Abstract Factory Method as change theme in our computer.

        When we change the theme, all the style of our button, window, text field controls have changed.

        It the same when we switch to another factory. All the products produced have changed accordingly.

       All we need to do when using the new created factory is to modify the config file.

    2) What's the advantage/disvantage of Simple Factory?

        --- 1) We can extends the kind of product, we merely need to create a corrosponding factory.

        --- 2) This would lead to Factory Flooding when we want to create a series of product.

    3) What's the advantage/disvantage of Abstract Factory?

        --- 1) We can easily create a whole new kind of factory that generate a series of product.

        --- 2) But we cannot extend the kind of product. For example, what if we want the the man is also with an armor?

                 We have to change the code of AbstractFactory as well as all the Factories that extends this AbstractFactory.

    4) How can we combine the advantages of the two kinds of factory together and discard the disadvantages?

        --- 1) There is a compromise solution in Spring framework called BeanFactory/BeanContainer/IOC.

        --- 2) Here BeanFactory is a factory created by Spring framework. When we using this, we don't have to create a factory for each of the beans defined in XML file.

        --- 3) But how can we control the process of creating new instance? What if we want to apply permission check before creation? Then it comes to AOP, another feature in Spring.

6. Summary

    1) The topic we disscussed is as below:

        1) What if there is only one car for the application?

            What if there is only 20 cars for the application?

            (Singleton/Multiton)

        2) What if we want to custom the process of creating vehicle and custom the type of the vehicle?

            (Simple Factory)

        3) What if we want to create a series of product like vehicle, weapon, food supply and armor?

            (Abstract Factory)

        4) What if we want to combine the benefits of Simple Factory with Abstract Factory?

            Spring Bean Factory -- Custom the process of generating production as well as the type of production.

                1) Custom the class according to a specific interface using IOC

                2) Custom the process of creating new instance using AOP.

猜你喜欢

转载自davyjones2010.iteye.com/blog/1881635