Announcement Announcement Module
Collapse
No announcement yet.
how to apply Factory design pattern into spring Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • how to apply Factory design pattern into spring

    Code:
    public class Factory{
    
      public static Sample creator(int which){
    
      if (which==1)
        return new SampleA();
      else if (which==2)
        return new SampleB();
    
      }
    
    }
    in above example, SampleA and SampleB are bean defined in applicationContext.xml. how can i process in this situation under spring .

  • #2
    this problem is how to create object dynamic under spring. if i use getBeanName method , it just means to create new object.but i always need factory class to decide which object is return. how to solve this problem under spring?

    Comment


    • #3
      Hundreds of ways.

      One is each bean name refers to an object: getBean("whichOne") gets you SampleA object, getBean("whichTwo") gets you SampleB, etc. Thus, your Factory will just do a ctx.getBean(which).

      I don't like this approach, seems to be duplicating what the Spring container is doing.

      Another is to create your own org.springframework.beans.factory.FactoryBean subclass that does what you need. Or just put your own factory into the context and use as the standard factory design pattern.

      I bet there are more elegant approaches.

      Comment


      • #4
        There is a new FactoryBean in 1.1.4: ServiceLocatorFactoryBean

        It creates factories out of an interface. Take a look at the JavaDocs for more details.

        Comment


        • #5
          i know implments FactoryBean interface can get object,but its getObject methods doesn't have an parameter. I don't know how to pass parameter to getObject methods. Anybody can give me example,thanks!

          Comment


          • #6
            The short answer is that: you can't. Any parameters you need to set on the object returned by a factory will need to be set by the class that calls the factory, not the factory itself.

            The longer answer is that you can write a FactoryBean that gives this behavior, but it's tricky. I've been thinking about the right way to do it for a bit. It would be nice if Spring contained one, out of the box.

            You can also create a bean that is BeanFactoryAware, and it can look up a bean via the BeanFactory, and then set parameters for you. But that couples Spring with your code, something that you are supposed to try to avoid.

            Comment


            • #7
              thank for your reply! if i select spring as my object manager,so i can not use factory design pattern. Object that i want to create is a bean defined in spring. I do not want my code depend on spring. But in my code,i really need factory design pattern to create object based on some condiction. how can i do now! :oops:

              what i do now is to wish spring team can support this function in later version!

              Comment


              • #8
                how to apply Factory design pattern into spring

                Hi all,

                Sorry if I am not getting the point, but what is wrong with the following approach?

                Code:
                	<bean id="SampleFactory" class="SampleFactoryImpl">
                		<property name="samples">
                			<list>
                				<bean class="SampleA">
                					<property name="someData"><value>A SAMPLE STRING</value></property>
                				</bean>
                				<bean class="SampleB">
                					<property name="someData"><value>2005</value></property>
                				</bean>
                			</list>
                		</property>
                	</bean>
                where the above classes are something along these lines:

                Code:
                public interface SampleFactory
                &#123;
                    public Sample getSample&#40;int which&#41;;
                &#125;
                
                public interface Sample
                &#123;
                    public void doSomething&#40;&#41;;
                &#125;
                
                public class SampleA implements Sample
                &#123;
                    private String someData;
                    
                    public void setSomeData&#40;String data&#41;
                    &#123;
                        someData = data;
                    &#125;
                    
                    public void doSomething&#40;&#41;
                    &#123;
                        System.out.println&#40;"SampleA doing something with " + someData&#41;;
                    &#125;
                &#125;
                
                public class SampleB implements Sample
                &#123;
                    private int someData;
                    
                    public void setSomeData&#40;int data&#41;
                    &#123;
                        someData = data;
                    &#125;
                    
                    public void doSomething&#40;&#41;
                    &#123;
                        System.out.println&#40;"SampleB doing something with " + someData&#41;;
                    &#125;
                &#125;
                
                public class SampleFactoryImpl implements SampleFactory
                &#123;
                    private List samples;
                    
                    public void setSamples&#40;List samples&#41;
                    &#123;
                        this.samples = samples;
                    &#125;
                    
                    public Sample getSample&#40;int which&#41;
                    &#123;
                        // no error checking!
                        return &#40;Sample&#41; this.samples.get&#40;which&#41;;
                    &#125;
                &#125;
                And where the "SampleFactory" is used as any other bean:

                Code:
                SampleFactory sampleFactory; // this reference is set by DI or lookup
                Sample s = sampleFactory.getSample&#40;1&#41;;
                Best regards,
                Fernando

                Comment


                • #9
                  The issue is if you want a new copy of Sample every time your factory is invoked. If you don't, your code is great. If you do, there's a problem.

                  Note that declaring the Sample beans to be prototypes instead of singletons will not be sufficient, as declaring a bean to be a prototype just means that every reference inside the Spring property file will be unique. Your factory would then return that object to every caller.

                  Comment


                  • #10
                    I see. In that case (a new instance of Sample is needed every time) I guess the easiest way would be to make SampleFactoryImpl implement BeanFactoryAware, as you said coupling the factory implementation with Spring (which may or may not be that bad).

                    Maybe even the original approach would be viable if the Sample implementations are clonable.

                    Thank you for clarifying the issue,
                    Fernando

                    Comment


                    • #11
                      Actually, you can solve the problems of different bean lifecycles using method injection, specifically lookup method injection. In this way a singleton can depend on a non-singleton, get a different instance whenever it needs and have no dependency on the BeanFactory.

                      See section 3.3.4.1 of the Spring reference manual for more information.

                      Rob

                      Comment


                      • #12
                        I've looked at method injection before, and it's left a bad taste in my mouth. I know, it's a matter of style, but it feels like too much magic.

                        It also fails in the case where you need to choose among several different implementations. The ServiceLocatorFactoryBean solves that problem, and feels "better" to me than method injection.

                        What I would love from Spring is a FactoryBean that will auto-generate a factory from an interface that looks like this:

                        Code:
                        public interface MyFactory &#123;
                             MyBean createOne&#40;int initParam1, int initParam2&#41;;
                        &#125;
                        
                        public interface MyBean &#123;
                             public int getSum&#40;&#41;;
                        &#125;
                        
                        public class MyBean1 implements MyBean &#123;
                             private int _sum;
                        
                            public MyBean1&#40;int initParam1, int initParam2&#41; &#123;
                               _sum = initParam1 + initParam2;
                            &#125;
                        
                             public int getSum&#40;&#41; &#123;
                                 return _sum;
                             &#125;
                        &#125;
                        Setters aren't fantastic for this, because I don't want to save the state that's being passed in; it's only used to create state that I do care about. Using setters would mean that I would (1) have to store values I don't need or want and (2) have to add another method to actually do the work after all the setters have been invoked, and add error checking to make sure that all of them have been invoked (boolean guard flags around each setter variable? A count to keep track of how many my set-up setters have been called?).

                        Solving problems like this in a simple way would really help.

                        Comment


                        • #13
                          Certainly, method lookup doesn't help when choosing between multiple implementations, but in that case you can use a direct BeanFactory lookup or use ServiceLocatorFactoryBean.

                          For your second point here regarding autogeneration of a factory that will map arguments to the constructor of some concrete type, I'm not sure what this solves that construcor injection does not. I'd be interested to hear your use case because implementation of what you are after should be quite simple.

                          Rob

                          Comment


                          • #14
                            My understanding is that Constructor Injection, like Setter Injection, is static. The values are defined in the Spring property file or XML file. If I want to construct a bean with different values for the parameters, I need to declare a new bean. This isn't scalable for unbounded input.

                            Going back to my example, imagine a trivial servlet that uses those classes to return the sum of any two numbers entered into a form on a web page and returns the sum. How would you solve this problem in Spring, exposing as little of Spring as possible?

                            (I realize that servlets can't have their dependencies be managed by Spring. However, I have written support classes that allow the creation of SpringServlets, which have a somewhat-hidden coupling to Spring. The discussion about them can be found at: http://forum.springframework.org/showthread.php?t=12528 . As that thread mentions, you can also inject the factory into the ServletContext via the ServletContextAttributeExporter.)

                            If I'm wrong about Constructor and Setter Injection, please let me know! I might be missing something obvious because I tried being clever...
                            Last edited by robyn; May 14th, 2006, 12:06 PM.

                            Comment


                            • #15
                              Servlet injection: Someone has written support for Servlet, JMS, ..., injection. Not sure when it will be added to Spring core.


                              Runtime arguments to getBean: This has been an ongoing discussion and is a Jira issue: http://opensource.atlassian.com/proj...browse/SPR-334

                              Comment

                              Working...
                              X