I am having a problem with Factory pattern when it use with Inheritance,
This is my code
public class Animal {
public int numberOfLegs() { return 2 ;}
}
public class Cat extends Animal {
public String getSound() {return "Maaaw";}
}
public class Dog extends Animal {
public String getSound() {return "woof";}
}
public class AnimalFactory {
public Animal getAnimal(String name){
Animal an= null ;
if(name=="cat"){an = new Cat();}
else if(name=="dog"){an=new Dog();}
return an ;
}
}
public class FactoryDemo {
public static void main(String[] args) {
AnimalFactory anmF=new AnimalFactory();
Animal anm=anmF.getAnimal("cat") ;
System.out.println("legs : "+anm.numberOfLegs()); // working fine
System.out.println("sound : "+anm.getSound()); // giving error
}
}
When I run this, I can't go to the getSound() method. It giving a error.
This'll work fine if I define the Animal class as Abstract class,
But I want to how to deal Factory pattern such a situation like this.
You need to add an abstract method for getSound
public abstract class Animal {
public int numberOfLegs() { return 2 ;}
public abstract String getSound();
}
Change your code to:
public abstract class Animal {
public int numberOfLegs() {
return 2;
}
public abstract String getSound();
}
public class Cat extends Animal {
public String getSound() {
return "Maaaw";
}
}
public class Dog extends Animal {
public String getSound() {
return "woof";
}
}
public class AnimalFactory {
public Animal getAnimal(String name) {
Animal an = null;
if ("cat".equals(name)) {
an = new Cat();
} else if ("dog".equals(name)) {
an = new Dog();
}
return an;
}
}
You shall add abstract method, and use equals in your factory method instead of using == on Objects.
The code you included, is nothing like a Factory anything. If you refer to the Factory Method Pattern then, what you implemented as part of your OP is an incorrect implementation. There are two "Factory" code designs, one is the Factory Method Pattern I indicated before (your code is definitely not that) and the Factory recommended in the Effective Java book, which is the design of choice for the Java JDK i.e. the valueOf or create* methods.
Related
I have some related classes that implement the same method
class Dog {
public void speak() { System.out.println("Bark") }
}
class Cat {
public void speak() { System.out.println("Meow") }
}
90% of the time, users would want both the dog and the cat to speak. They don't want to know the details. When we add a new animal, they'll want it to speak too. The idea is to avoid:
// All animals need to be explicitly told to speak every time
new Dog().speak();
new Cat().speak();
// But we just added Birds, and the users need to remember to add this call everywhere
new Bird.speak();
I could do something like
class Animals {
public void speak() {
new Dog().speak();
new Cat().speak();
new Bird().speak();
}
}
So that users can just call new Animals().speak() every time.
However, 10% of the time, it does need to be configurable. What I want is a way for users to do something like this
// Used most of the time
Animals.withAllAnimals().speak();
// Sometimes they don't want cats, and they want the dogs to woof instead
Animals.exclude(Cat)
.configure(Dog.sound, "Woof")
.speak();
How can I structure my classes to accomplish this?
I know that it is question tagged with java. However, let me show an example with C# as these languages have many common things.
The first thing is I would use inheritance and create abstract class Animal as common behaviour Speak() is used. So, abstract class should define behavior, and the derived classes should implement that behavior:
public abstract class Animal
{
public abstract void Speak();
}
Then just use inheritance and override behaviour in derived classes:
public class Bird : Animal
{
public override void Speak()
{
System.Console.WriteLine("I am a bird!");
}
}
public class Cat : Animal
{
public override void Speak()
{
System.Console.WriteLine("I am a cat!");
}
}
public class Dog : Animal
{
public override void Speak()
{
System.Console.WriteLine("I am a dog!");
}
}
Then we need a class that allows to speak for all animals. Let's create Choir class for this purpose:
public class Choir
{
private List<Animal> choristers;
public void AddChoristers(IEnumerable<Animal> choristers)
{
if (choristers == null)
choristers = new List<Animal>();
choristers.AddRange(choristers);
}
public void SpeakAll()
{
foreach (Animal animal in choristers)
animal.Speak();
}
public void Speak(Func<Animal, bool> filter)
{
IEnumerable<Animal> filteredAnimals = choristers
.Where(filter ?? (animal => true));
foreach (Animal animal in filteredAnimals)
animal.Speak();
}
}
Pay attention to Speak() method. It can take a predicate as a parameter, so you can choose desired animals to speak().
Here are some ideas.
import java.util.*;
import java.util.function.Consumer;
/**
* An animal can either speak with its own voice, or another supplied
*/
interface Animal {
String speak();
String speak(String voice);
}
/**
* Base class for animal implementations.
*
* An animal is added to a Menagerie when created.
*/
abstract class BaseAnimal implements Animal {
private final String defaultVoice;
public BaseAnimal(Menagerie menagerie, String defaultVoice) {
this.defaultVoice = defaultVoice;
menagerie.add(this);
}
public String speak(String voice) {
return voice;
}
public String speak() {
return speak(defaultVoice);
}
}
/**
* A Dog. Even when given a voice the dog does things slightly differently.
*/
class Dog extends BaseAnimal {
public Dog(Menagerie menagerie) {
super(menagerie, "Bark!");
}
public String speak(String voice) {
return voice + " (and drools)";
}
}
/**
* A collection of animals. We can do something side-effectful to each, or create a new collection where
* some classes of animal are excluded or have different behaviour.
*/
interface Animals {
void forEach(Consumer<Animal> action);
Animals exclude(Class<Animal> clazz);
Animals configureVoice(Class<Animal> clazz, String voice);
}
/**
* An Animals instance which can contain only a single animal of each class
* (an arbitrary decision based on the code in the question)
*/
class Menagerie implements Animals {
Map<Class<? extends Animal>,Animal> animals = new HashMap<>();
public Menagerie() {
}
public Menagerie(Map<Class<? extends Animal>, Animal> animals) {
this.animals = new HashMap<>(animals);
}
public void add(Animal animal) {
animals.put(animal.getClass(), animal);
}
public void forEach(Consumer<Animal> action) {
animals.values().forEach(action);
}
#Override
public Animals exclude(Class<Animal> clazz) {
Menagerie m = new Menagerie(animals);
m.animals.remove(clazz);
return m;
}
/**
* Return an Animals instance which contains a proxy for a particular type of animal
* which will behave differently when speak() is called.
*/
#Override
public Animals configureVoice(Class<Animal> clazz, String voice) {
Menagerie m = new Menagerie(animals);
Animal a = m.animals.get(clazz);
if (a != null) {
m.animals.put(clazz, new Animal() {
#Override
public String speak() {
return voice;
}
#Override
public String speak(String voice) {
return a.speak(voice);
}
});
}
return m;
}
}
I have abstract class Pet with abstract method feed(...). The method must take only on of certain three types of food (DRY, WET or RAW). These can be String type as I use them only as indicators in SWITCH in later logic. Also I have two subclasses Cat and Dog. They implement the feed(...) method from Pet. The closest I came to, is using ENUM:
Pet.java:
public abstract class Pet {
public enum FoodType {
DRY,
WET,
RAW;
}
public abstract void feed(FoodType foodType);
}
Cat.java:
public class Cat extends Pet {
public void feed(FoodType foodType) {
switch (foodType) {
case DRY:
System.out.println("Feeding this cat dry food.");
break;
case RAW:
System.out.println("Feeding this cat raw food.");
break;
case WET:
System.out.println("Feeding this cat wet food.");
break;
}
}
}
Dog.java:
public class Dog extends Pet {
public void feed(FoodType foodType) {
// implementation similar to feed() in Cat.
}
}
App.java:
import pets.Dog;
import pets.Pet;
public class App {
public static void main(String[] args) {
Dog dog01 = new Dog();
dog01.feed(Pet.FoodType.DRY);
}
}
But I don't like that, since ENUMS are static by default FoodType can be accessed from anywhere in project. Without creating a Cat or Dog object, i can call Pet.FoodType.DRY from anywhere. Preferebly it should be associated only with an object that inherits from Pet, eg:
Dog dog01 = new Dog();
dog01.FoodType.DRY; // do smth with this
This is happening because you have declared FoodType as public. Please replace that with protected and this issue will be resolved.
protected enum FoodType
Alternatively to resolve this issue probably we can implement that as business logic
public abstract class Pet {
protected String[] foodType = new String[]{"RAW","DRY","WET"};
protected final String RAW_FOOD_TYPE = "RAW";
protected final String DRY_FOOD_TYPE = "DRY";
protected final String WET_FOOD_TYPE = "WET";
public abstract void feed(String foodType);
public String getRawFoodType()
{
return RAW_FOOD_TYPE;
}
public String getDryFoodType()
{
return DRY_FOOD_TYPE;
}
public String getWetFoodType()
{
return WET_FOOD_TYPE;
}
}
public class Cat extends Pet {
public void feed(String foodType)
{
if(foodType.equals(DRY_FOOD_TYPE))
{
System.out.println("Feeding this cat dry food.");
}
else if(foodType.equals(RAW_FOOD_TYPE))
{
System.out.println("Feeding this cat raw food.");
}
else if(foodType.equals(WET_FOOD_TYPE))
{
System.out.println("Feeding this cat wet food.");
}
else
{
throw new RuntimeException("Invalid foodtype");
}
}
}
public class App {
public static void main(String[] args) {
Cat cat01 = new Cat();
cat01.feed(cat01.getDryFoodType());
}
}
```
So usally it should be fine to have public enum in practise for this. But to answer your question yes it is possible by modifying the structure a bit. So the constants here could be as enum or as private final string both would be fine.
Taking this case for enum, declare it as protected. Then create a method which will return the enum value inside the Pet class itself , which is essentially wrapping this in a getter.
public FoodType getFoodType(String foodTypeStr){
return FoodType.valueOf(foodTypeStr);
}
This will make sure only instance variables of child classes can invoke it. Hence you can do something like this,
dog01.feed(dog01.getFoodType("DRY"));
This can be made protected and ovveriden in child if needed.
I tried to implement a function in a base class which using the function of the childs (defiend as a abstract function in the base class). I think an example will demonstrate the problem in the best way.
abstract class Animal{
public void doSomthing(){
this.sound();
}
protected abstract void sound();
}
class Dog extends Animal{
#Override
protected void sound(){
System.out.println("WAF");
}
}
now when I tried to get the element in run time (by factory method which looks like: Animal factory method("Dog);) and call to the doSomthing method I got exception because it goes to the abstract method, my question is if there is any way the bypass this or another solution for this problem.
class myMain
{
public static void main(String[]args)
{
Animal doggo = new Dog(); // create object for dog
doggo.animalSound(); // call the sound for dog
}
}
class Animal
{
public void animalSound()
{
System.out.println("The animal makes a sound");
}
}
class Dog extends Animal
{
public void animalSound()
{
System.out.println("The Dog Says bow wow! ");
}
}
I do not see any problem with the approach you have mentioned in the description of your question. Maybe you are doing some other mistake. Check the following working code:
abstract class Animal {
public void doSomthing() {
sound();
}
protected abstract void sound();
}
class Dog extends Animal {
#Override
protected void sound() {
System.out.println("WAF");
}
}
class AnimalFactory {
static Animal animal;
public static Animal factoryMethod(String animalName) {
if ("Dog".equals(animalName)) {
animal = new Dog();
}
return animal;
}
}
class Main {
public static void main(String[] args) {
Animal animal = AnimalFactory.factoryMethod("Dog");
animal.sound();
}
}
Output:
WAF
The call to child class method from super class can be done.
Refer code snippet mentioned in below link:
Can a Parent call Child Class methods?
It may look similar to my question. I have a simple animal factory.
public class AnimalFactory {
public Animal getAnimal(String type) {
if ("canine".equals(type)) {
return new Dog();
} else {
return new Cat();
}
}
}
and class for
public interface Animal {
void makeSound();
}
public class Dog extends Animal {
void makeSound() {
}
}
public class Dog extends Animal {
void makeSound() {
}
}
I have some doubts. Does AnimalFactory violate the dependency inversion principle? Is it possible to unit test AnimalFactory without making calls to the actual Dog and Cat classes or do I have to refactor my code?
You're not violating the dependency inversion principle if there are no dependencies to inject.
In any case the Factory is a creational design pattern and you should test that it does indeed create (instantiate) the right things.
Yes, you should test that it does return objects where instanceof Dog and instanceof Cat are true.
If you must test your factory without actually calling the constructors of Dog and Cat (due to the initialization that they do), I suggest refactoring the factory class like this:
public class AnimalFactory {
public Animal createAnimal(String type) {
if ("canine".equals(type)) {
return createDog();
} else {
return createCat();
}
}
Dog createDog() { return new Dog(); }
Cat createCat() { return new Cat(); }
}
And the test would look like this:
public class AnimalFactoryTest {
#Test
public void testCreateDog() throws Exception {
AnimalFactory mockFactory = mock(AnimalFactory.class);
when(mockFactory.createAnimal(anyString())).thenCallRealMethod();
mockFactory.createAnimal("canine");
verify(mockFactory).createDog();
}
#Test
public void testCreateCat() throws Exception {
AnimalFactory mockFactory = mock(AnimalFactory.class);
when(mockFactory.createAnimal(anyString())).thenCallRealMethod();
mockFactory.createAnimal("cat");
verify(mockFactory).createCat();
}
}
Incidentally, the naming convention for Factory pattern methods are createXyz rather than getXyz.
Good luck.
it may looks like a dummy question for you but I have difficulties solving this:
We have an abstract class Animal and Cat and Dog that extends it. In Animal we have a method produceSound(); that is abstract. As you can probably guess for Cat it should return "Mao" and for Dog - "Bao" or something like that. This is OK but now we must write a static method in the Animal class that returns Cat or Dog objects depending on their sound. For example: identifyAnimal("Mao") should return Cat.
Question: How to implement the identifyAnimal(String sound) method?
Here is some simple example of the hierarchy:
Animal class
public abstract class Animal {
protected abstract String produceSound();
protected static void identifyAnimal(String animalSound) {
// TODO
}
}
Cat class
public class Cat extends Animal{
#Override
protected String produceSound() {
return "Mao";
}
}
Dog class
public class Dog extends Animal{
#Override
protected String produceSound() {
return "Bao";
}
}
Test class
public class AnimalTest {
public static void main(String[] args) {
Animal.identifyAnimal("Bao");
}
}
In the AnimalTest class when calling the Animal.identifyAnimal("Bao"); we should get a Dog.
private static Class[] animalTypes = [Dog.class, Cat.class];
public static String identifyAnimal(String animalSound)
{
for (int i = 0; i < animalTypes.length; i++) {
Animal a = animalTypes[i].newInstance();
String s = a.produceSound();
if (animalSound.equals(s))
return animalTypes[i].getName();
}
return null;
}
So here a (terrible) way to do this. I actually twitched a little.
I don't know what language you are using, so I'm going with c++(sorry current mode) though you could replace maps with Dictionaries if we are in C#, whatever. This is a bad way to go about things, but should work(conceptually, anyway)
Again...Terrible...
public abstract class Animal {
protected abstract String produceSound();
protected static map<string, string> SoundList;
protected static bool registerSound(string sound, string type)
{
return (SoundList.insert( pair<string, string>(sound, type)))->second;//true if worked false if already there
}
protected static string identifyAnimal(string animalSound)
{
map<string,string>::iterator result = SoundList.find(sound);
if(result != SoundList.end())
return result->second;
else
return "What The Hell Is This!?";
}
}
Cat class
public class Cat extends Animal
{
Cat()
{
Animal::registerSound("Mao","Cat");
}
#Override
protected String produceSound() {
return "Mao";
}
}
abstract class Animal {
static Map<String,String> map = new HashMap<String,String>();
public Animal(String value) { map.put(produceSound(), value); }
protected abstract String produceSound();
protected static void identifyAnimal(String animalSound) {
System.out.println(map.get(animalSound));
}
}
class Cat extends Animal {
#Override
protected String produceSound() { return "Mao"; }
Cat(){ super("CAT"); }
}
class Dog extends Animal {
#Override
protected String produceSound() { return "Bao"; }
Dog(){ super("DOG"); }
}
class Test {
public static void main(String[] args) {
new Dog();
new Cat();
Animal.identifyAnimal("Bao");
}
}
Do a switch with the predefined sounds that you have and let each sound return a string with the name of the animal. For example "Mao" returns a string "Cat" and so on.
One more thing let ur identifyAnimal method returna string instead of void.
You could use reflection to get a list of all types that extend Animal, loop through them using Activator to create instances of each type running produceSound on each until you find the return value that matches animalSound, returning that instance. Slow, but effective if you want to avoid your Animal class being aware of what extends it.
What is the nature of the problem you are trying to solve? There is no 'right' way that is independent of the problem.
What does the consuming application need from the class Animal? What does your application need to do with the classes that it consumes? Nothing can be assumed unless these presumptions are clear.