I came across a term called reflection. It is a feature commonly used in factory design patterns. I had a hard time understanding the concept because I’m still learning how to program. How can reflection be used in factory design patterns in C# or Java? Can anyone give me a simple example, and show me your code that uses reflection to implement factory design patterns?
Microsoft provides this code example of reflection, but i don't see how this can be used in factory design patterns.
// Using GetType to obtain type information:
int i = 42;
System.Type type = i.GetType();
System.Console.WriteLine(type);
The Output is: System.Int32
I would never use reflection to implement Factory design pattern, unless there was a special case. The below code is a terrible way to implement the factory design pattern. But since you wanted to know "How" to use reflection for factory design pattern here's the example:
namespace NaiveFactory
{
public interface Shape
{
void Draw();
}
public class Circle : Shape
{
public void Draw() { Console.WriteLine("Drawing Circle"); }
}
public class Rectangle : Shape
{
public void Draw() { Console.WriteLine("Drawing Rectangle"); }
}
public class ShapeFactory
{
public static Shape GetShape<T>() where T : Shape
{
return Activator.CreateInstance<T>();
}
public static Shape GetShape(string shapeName)
{
var assembly = Assembly.GetExecutingAssembly();
var type = assembly.GetType(shapeName).FullName;
return (Shape) Activator.CreateInstanceFrom(assembly.Location, type).Unwrap();
}
}
class Program
{
static void Main(string[] args)
{
var shape = ShapeFactory.GetShape<Circle>();
var shape2 = ShapeFactory.GetShape("NaiveFactory.Rectangle");
shape.Draw();
shape2.Draw();
Console.ReadKey();
}
}
}
EDIT
As per suggestion from #AlexeiLevenkov, I have added something close to Dependency injection and instantiating the Shape objects using Constructor Injection as well as with a method:
namespace NaiveFactory
{
public interface IBoard
{
void InternalDraw(string str);
}
public class ConsoleBoard : IBoard
{
public void InternalDraw(string str) { Console.WriteLine(str); }
}
public class DebugBoard : IBoard
{
public void InternalDraw(string str) { Debug.WriteLine(str); }
}
public interface Shape
{
IBoard Board { get; set; }
void Draw();
void SetBoard(IBoard board);
}
public class Circle : Shape
{
public IBoard Board { get; set; }
public Circle()
{
}
public Circle(IBoard board)
{
Board = board;
}
public void Draw() { Board.InternalDraw("Drawing Circle"); }
public void SetBoard(IBoard board)
{
Board = board;
}
}
public class Rectangle : Shape
{
public IBoard Board { get; set; }
public Rectangle()
{
}
public Rectangle(IBoard board)
{
Board = board;
}
public void Draw() { Board.InternalDraw("Drawing Rectangle"); }
public void SetBoard(IBoard board)
{
Board = board;
}
}
public class ShapeFactory
{
private static Dictionary<Type, Type> _configurationData = new Dictionary<Type, Type>();
public static Shape GetShape<T>() where T : Shape
{
return Activator.CreateInstance<T>();
}
public static void ConfigureContainer<T, U>()
{
_configurationData.Add(typeof(T), typeof(U));
}
public static Shape GetShape_UsingConstructorInjection(string shapeName)
{
var assembly = Assembly.GetExecutingAssembly();
var type = assembly.GetType(shapeName);
var constructor = type.GetConstructor(_configurationData.Keys.ToArray());
if (constructor != null)
{
var parameters = constructor.GetParameters();
return (from parameter in parameters where _configurationData.Keys.Contains(parameter.ParameterType)
select Activator.CreateInstance(_configurationData[parameter.ParameterType]) into boardObj
select (Shape) Activator.CreateInstance(type, boardObj)).FirstOrDefault();
}
return null;
}
public static Shape GetShape_UsingSetBoardMethod(string shapeName)
{
var assembly = Assembly.GetExecutingAssembly();
var type = assembly.GetType(shapeName);
var shapeObj = (Shape) Activator.CreateInstance(type);
if (shapeObj != null)
{
shapeObj.SetBoard((IBoard) Activator.CreateInstance(_configurationData[typeof (IBoard)]));
return shapeObj;
}
return null;
}
}
class Program
{
static void Main(string[] args)
{
ShapeFactory.ConfigureContainer<IBoard, ConsoleBoard>();
var shape = ShapeFactory.GetShape_UsingSetBoardMethod("NaiveFactory.Circle");
var shape2 = ShapeFactory.GetShape_UsingConstructorInjection("NaiveFactory.Rectangle");
shape.Draw();
shape2.Draw();
Console.ReadKey();
}
}
}
Java version for this question
Code:
public class TestReflectionFactoryDesign {
public static void main(String[] args) throws Exception {
Person student = PersonFactory.getPersonWithFullQualifiedClassName("com.test.reflectionFactoryDesign.Student");
student.say();
Person teacher = PersonFactory.getPersonWithClass(Teacher.class);
teacher.say();
Person student2 = PersonFactory.getPersonWithName("student");
student2.say();
}
}
class Student implements Person {
#Override
public void say() {
System.out.println("I am a student");
}
}
class Teacher implements Person {
#Override
public void say() {
System.out.println("I am a teacher");
}
}
interface Person {
void say();
}
class PersonFactory {
// reflection, by full qualified class name
public static Person getPersonWithFullQualifiedClassName(String personType) throws Exception {
Class<?> personClass = Class.forName(personType);
return getPersonWithClass(personClass);
}
// reflection, by passing class object
public static Person getPersonWithClass(Class personClass) throws Exception {
return (Person) personClass.newInstance();
}
// no reflection, the ordinary way
public static Person getPersonWithName(String personType) {
if (personType.equalsIgnoreCase("STUDENT")) {
return new Student();
} else if (personType.equalsIgnoreCase("TEACHER")) {
return new Teacher();
}
return null;
}
}
Output:
I am a student
I am a teacher
I am a student
Related
For example, if I wanted to do something like this to call a method:
myLights.addLight(new Fluorescent(lumens));
in order to create a new object in the Fluorescent class and pass down the lumens data. How would I then set up the method to receive this?
Assuming method is not returning anything.
void addlight(Fluorescent a){
// your logic
}
In your Lights class create a method that accepts a Fluorescent object as an argument.
public void addLight(Fluorescent fluorescent){
// do something
}
Here is a basic example:
public class HelloWorld
{
public static void main(String[] args)
{
Light light = new Light();
light.addLight(new Fluorescent("300 lm"));
System.out.print(light.getLumen());
}
}
public class Light {
private String lumen;
public Light() {
}
public void setLumens(String lumen){
this.lumen = lumen;
}
public String getLumen(){
return this.lumen;
}
public void addLight(Fluorescent fluorescent) {
if(fluorescent.getLumen() != null) {
this.lumen = fluorescent.getLumen();
}
}
}
public class Fluorescent {
private String lumen;
public Fluorescent(String lumen){
this.lumen = lumen;
}
public void setLumen(String lumen){
this.lumen = lumen;
}
public String getLumen(){
return this.lumen;
}
}
Seeing that a Fluorescent is a Light, you might want to look in to inheritance.
Look here for some explanation
Java 101: Inheritance in Java, Part 1
public class Fluorescent() {
public Fluorescent(String lumens) {
// do something
}
}
public class Lights() {
public void addLight(Fluorescent fluorescent) {
// do something
}
}
I'm using the Java instanceof but it doesn't seem to be working.
I have three java classes that extend a Hero class.
The Hero.java class:
public abstract class Hero {
protected int health;
public Hero() {
}
}
The other three classes:
public class Archer extends Hero {
public Archer() {
}
}
public class Mage extends Hero {
public Mage() {
}
}
public class Warrior extends Hero {
public Warrior() {
}
}
I have this main class WelcomeScreen.java
public class WelcomeScreen {
private Archer archer;
private Mage mage;
private Warrior warrior;
private Hero hero;
public WelcomeScreen() {
// choose a hero (archer/mage/warrior)
hero = archer;
new Game(hero);
}
public static void main(String args[]) {
new WelcomeScreen();
}
}
that instantiates the Game.java class
public class Game {
public Game(Hero chosenHero) {
if (chosenHero instanceof Mage) {
System.out.println("you selected mage");
} else if (chosenHero instanceof Archer) {
System.out.println("you selected archer");
} else if (chosenHero instanceof Warrior) {
System.out.println("you selected warrior");
} else {
System.out.println("you selected NOTHING");
}
}
}
In Game.java, the code is meant to check whether chosenHero is an object of Archer.java, Warrior.java, or Mage.java, but I result with "you selected NOTHING". Why does instanceof fail to check if I already assigned it to Archer.java in the WelcomeScreen?
Because your constants are null. When you say,
private Archer archer;
it is equivalent to
private Archer archer = null;
Additionally, you have created three fields per instance. I think you wanted to do something like
private static final Hero archer = new Archer();
private static final Hero mage = new Mage();
private static final Hero warrior = new Warrior();
See also What does it mean to “program to an interface”?
Alternative solution: get rid of instanceof as it suggests a brittle rigid design, one that's easily broken. Instead try to use other more OOP-compliant solutions such as inheritance, or if complex, a Visitor Design Pattern.
For example, a simple inheritance structure could look something like:
public class WelcomeScreen {
public WelcomeScreen() {
// choose a hero (archer/mage/warrior)
Hero hero = new Archer();
new Game(hero);
}
public static void main(String args[]) {
new WelcomeScreen();
}
}
abstract class Hero {
protected int health;
// other shared fields such as String name,...
public Hero() {
}
public abstract String getType();
public int getHealth() {
return health;
}
}
class Archer extends Hero {
public static final String TYPE = "Archer";
public Archer() {
}
#Override
public String getType() {
return TYPE;
}
}
class Mage extends Hero {
public static final String TYPE = "Mage";
public Mage() {
}
#Override
public String getType() {
return TYPE;
}
}
class Warrior extends Hero {
public static final String TYPE = "Warrier";
public Warrior() {
}
#Override
public String getType() {
return TYPE;
}
}
class Game {
private Hero hero;
public Game(Hero chosenHero) {
this.hero = chosenHero;
System.out.println("You selected a hero of type " + hero.getType());
}
}
I have the following need and please help me to write good and abstract class.
Different types of operations is needed based on the type
I have a abstract class,
abstract public class FileHelper{
//Template method
//This method defines a generic structure for parsing data
public void parseDataAndGenerateFile(String fileDownloadType)
{
createHeader(fileDownloadType);
generateFile();
}
//We have to write output in a excel file so this step will be same for all subclasses
public void createHeader(String fileDownloadType)
{
System.out.println('Creating HEADER in EXCEL');
}
public void generateFile(String fileDownloadType)
{
System.out.println('Output generated,writing to XLX');
}
}
public class ExcelDataParser extends FileHelper {
String fileDownloadType="";
}
public class TemplateMethodMain {
public static void main(String[] args) {
String fileDownloadType="expired";
ExcelDataParser csvDataParser=new ExcelDataParser();
csvDataParser.parseDataAndGenerateFile(fileDownloadType);
}
}
Please help me and correct me to have a good way of doing this.
If you want to use an abstract base class, you better should declare an abstract method String getDownloadType() in your abstract base class. These method must be overridden by the derived classes and the type could be fix in the derived class.
For example:
abstract public class FileHelper {
abstract String getFileDownloadType();
public void parseDataAndGenerateFile() {
createHeader();
generateFile();
}
public void createHeader() {
if ("expired".equals(getFileDownloadType())) {
} else {
}
}
public void generateFile() {
if ("expired".equals(getFileDownloadType())) {
} else {
}
}
}
public class ExcelDataParser extends FileHelper {
#Override
String getFileDownloadType() {
return "expired";
}
}
public class TemplateMethodMain {
public static void main(String[] args) {
ExcelDataParser csvDataParser = new ExcelDataParser();
csvDataParser.parseDataAndGenerateFile();
}
}
But if you don't need a class for every type, you also could make the type a variable inside a single class and passing the type to the contructor
For example:
public class CsvFileHelper {
private final String fileDownloadType;
public CsvFileHelper(String type) {
fileDownloadType = type;
}
public void parseDataAndGenerateFile() {
createHeader();
generateFile();
}
public void createHeader() {
if ("expired".equals(fileDownloadType)) {
} else {
}
}
public void generateFile() {
if ("expired".equals(fileDownloadType)) {
} else {
}
}
}
public class TemplateMethodMain {
public static void main(String[] args) {
CsvFileHelper csvDataParser = new CsvFileHelper("expired");
csvDataParser.parseDataAndGenerateFile();
}
}
MyMath's constructor is supposed to call Homework's constructor, but super(); returns an error 'cannot find symbol'. It should not have any arguments.
Also, I am confused about how to call the method createAssignment using an arraylist, but I have to use it. Any advice?
Homework
public abstract class Homework {
private int pagesToRead;
private String typeHomework;
public Homework(int pages, String hw) {
// initialise instance variables
pagesToRead = 0;
typeHomework = "none";
}
public abstract void createAssignment(int p);
public int getPages() {
return pagesToRead;
}
public void setPagesToRead(int p) {
pagesToRead = p;
}
public String getTypeHomework() {
return typeHomework;
}
public void setTypeHomework(String hw) {
typeHomework = hw;
}
}
MyMath
public class MyMath extends Homework {
private int pagesRead;
private String typeHomework;
public MyMath() {
super();
}
public void createAssignment(int p) {
setTypeHomework("Math");
setPagesToRead(p);
}
public String toString() {
return typeHomework + " - " + pagesRead;
}
}
public class testHomework {
public static void main(String[] args) {
ArrayList<Homework> list = new ArrayList<Homework>();
list.add(new MyMath(1));
list.add(new MyJava(1));
for (Homework s : list) {
s.createAssignment();
}
}
}
Compiler error:
Regarding the compiler error, you have to change the MyMath constractor to somthing like:
public MyMath() {
super(someInt, someString);
}
Or, you can add a non-arg constructor to the Homework class:
public Homework() {
this(someInt,someString);
}
You can learn about the super() keyword in the Javadocs tutoriel:
If a constructor does not explicitly invoke a superclass constructor,
the Java compiler automatically inserts a call to the no-argument
constructor of the superclass. If the super class does not have a
no-argument constructor, you will get a compile-time error. Object
does have such a constructor, so if Object is the only superclass,
there is no problem.
Code Suggestion:
As there is many other issues in your question, i modified all your classes like below:
Homework.java:
public abstract class Homework {
private int pagesToRead;
private String typeHomework;
{
// initialise instance variables
pagesToRead = 0;
typeHomework = "none";
}
public Homework(int pages, String hw) {
this.pagesToRead = pages;
this.typeHomework = hw;
}
public abstract void createAssignment(int p);
public int getPages() {
return pagesToRead;
}
public void setPagesToRead(int p) {
pagesToRead = p;
}
public String getTypeHomework() {
return typeHomework;
}
public void setTypeHomework(String hw) {
typeHomework = hw;
}
}
MyMath.java
public class MyMath extends Homework {
private int pagesRead;
private String typeHomework;
public MyMath(int pages, String hw) {
super(pages,hw);
}
public void createAssignment(int p) {
setTypeHomework("Math");
setPagesToRead(p);
}
public String toString() {
return typeHomework + " - " + pagesRead;
}
}
TestHomework.java:
class TestHomework {
public static void main(String[] args) {
ArrayList<Homework> list = new ArrayList<Homework>();
// will create a homework with type Math and one page to read
list.add(new MyMath(1,"Math"));
// Assuming MyJava is similar to MyMath
list.add(new MyJava(1,"Java"));
for (Homework s : list) {
if (s instanceof MyMath) {
// modify the number of pages to read for the Math homework
s.createAssignment(3);
} else if (s instanceof MyJava) {
// modify the number of pages to read for the Java homework
s.createAssignment(5);
} else {
s.createAssignment(7);
}
}
}
}
Lets say that I have a Composite set up as follows:
public abstract class Element {
//position, size, etc.
//element methods
//setters/getters
}
public class SimpleElement1 extends Element {
//...
}
public class SimpleElement2 extends Element {
//...
}
public class CompositeElement extends Element {
protected List<Element> childrenElements;
//methods to add/remove/get children
}
Now, how would I go about wrapping this Composite up into a Builder pattern, so that I can simplify client code by enabling it not to care (or care less) about the intricacies of how to link children to their Composite?
In your builder, add methods "startComposite" and "endComposite". These methods push a composite onto a stack and remove a composite from the stack. Messages to add elements always add to the top of stack.
builder.startComposite();
builder.simpleElement1();
builder.simpleElement2();
builder.endComposite();
builder.startComposite();
builder.simpleElement2();
builder.endComposite();
If your builder methods always return the builder, you can eliminate the repetition of the receiver:
builder.
startComposite().
simpleElement1().
simpleElement2().
endComposite().
startComposite().
simpleElement2().
endComposite();
Here is an example of a builder making an animal composite of different animal parts. You should be able to modify it for your particular application.
class BuilderDesignPattern{
public static void Main(string[] args)
{
Kid aKid = new Kid();
aKid.Name = "Elizabeth";
AnimalBuilder builderA = new MonkeyBuilder();
aKid.MakeAnimal(builderA);
builderA.aAnimal.ShowMe();
AnimalBuilder builderB = new KittenBuilder();
aKid.MakeAnimal(builderB);
builderB.aAnimal.ShowMe();
}
}
public abstract class AnimalBuilder
{
public Animal aAnimal;
public abstract void BuildAnimalHeader();
public abstract void BuildAnimalBody();
public abstract void BuildAnimalLeg();
public abstract void BuildAnimalArm();
public abstract void BuildAnimalTail();
}
public class MonkeyBuilder : AnimalBuilder
{
public MonkeyBuilder()
{
aAnimal = new Monkey();
}
public override void BuildAnimalHeader()
{
aAnimal.Head = "Moneky's Head has been built";
}
public override void BuildAnimalBody()
{
aAnimal.Body = "Moneky's Body has been built";
}
public override void BuildAnimalLeg()
{
aAnimal.Leg = "Moneky's Leg has been built";
}
public override void BuildAnimalArm()
{
aAnimal.Arm = "Moneky's Arm has been built";
}
public override void BuildAnimalTail()
{
aAnimal.Tail = "Moneky's Tail has been built";
}
}
public class KittenBuilder : AnimalBuilder
{
public KittenBuilder()
{
aAnimal = new Kitten();
}
public override void BuildAnimalHeader()
{
aAnimal.Head = "Kitten's Head has been built";
}
public override void BuildAnimalBody()
{
aAnimal.Body = "Kitten's Body has been built";
}
public override void BuildAnimalLeg()
{
aAnimal.Leg = "Kitten's Leg has been built";
}
public override void BuildAnimalArm()
{
aAnimal.Arm = "Kitten's Arm has been built";
}
public override void BuildAnimalTail()
{
aAnimal.Tail = "Kitten's Tail has been built";
}
}
public abstract class Animal
{
public BodyPart Head { get; set; }
public BodyPart Body { get; set; }
public BodyPart Leg { get; set; }
public BodyPart Arm { get; set; }
public BodyPart Tail { get; set; }
//helper method for demo the Polymorphism, so we can
//easily tell what type object it is from client.
public abstract void Eat();
//helper method for demo the result from client
public void ShowMe()
{
Console.WriteLine(Head);
Console.WriteLine(Body);
Console.WriteLine(Leg);
Console.WriteLine(Arm);
Console.WriteLine(Tail);
Eat();
}
}
public class Monkey : Animal
{
//helper method to show monkey's property for demo purpose
public override void Eat()
{
Console.WriteLine("Since I am Monkey, I like to eat banana");
}
}
public class Kitten : Animal
{
public override void Eat()
{
Console.WriteLine("Since I am Kitten, I like to eat kitten food");
}
}
public class Kid
{
public string Name { get; set; }
//construct process to build an animal object,
//after this process completed, a object
//will be consider as a ready to use object.
public void MakeAnimal(AnimalBuilder aAnimalBuilder)
{
aAnimalBuilder.BuildAnimalHeader();
aAnimalBuilder.BuildAnimalBody();
aAnimalBuilder.BuildAnimalLeg();
aAnimalBuilder.BuildAnimalArm();
aAnimalBuilder.BuildAnimalTail();
}
}
public class BodyPart{
String name= "";
public BodyPart(String name){
this.name=name;
}
}
}