Doubts? Improved? From simple factory to factory method

Source: Internet
Author: User
Keywords Nbsp; fact name okay new.

It's written in front.

A recent study on design patterns read the Terrylee and Lu Zhenyu two teachers wrote a series of design patterns, the harvest is quite abundant, but also let me have a new understanding and understanding of Oop,ood, but in the factory to see a few articles, but there is always a place to think, Hope that teachers and experts can answer for the next question, the following is their own understanding of the factory model and proposed an improvement plan, do not know whether someone has proposed similar scheme, if there is a coincidence. Please criticize me for the wrong place.

Speaking from a simple factory

Strictly speaking, a simple factory does not belong to one of the 23 design patterns of GOF, but the reason why it exists and is widely recognized, I think, is that it simplifies the pattern of factory methods (Factory method) and abstract factory (abstraction Factory) to some extent, So that you can bring the novice to the factory model design the essence of the most intuitive understanding, is a lot of people contact the cornerstone of the factory model, understand the simple factory design concept and implementation methods to understand the relatively complex factory methods and abstract factory has the effect.

Let's take a look at a simple factory class diagram:

Simple factories are generally implemented as follows:

public class Simplefactory


{


///


///Get the right product base on the paoductcategory parameter.


///


///


///


public static IProduct createproduct (string productcategory)


{


switch (productcategory)


{


case "A":


return new ProductA ();


case "B":


return new PRODUCTB ();


case "C":


return new PRODUCTC ();


Default:


throw new Exception ("not a valid product category!");


return null;


}


}


}

Customers ' use of simple factories

public class Client


{


public void Do ()


{


//create a producta


iproduct Product = simplefactory.createproduct ("A");


//product doing its tasks.


product. ExecuteFunction1 ();


product. ExecuteFunction2 ();


product. ExecuteFunction3 ();


product. ExecuteFunction4 ();


//more tasks.


}


}

At this point, if the customer is going to make product B, then all he has to do is modify the incoming factory parameters to tell the factory what needs to be produced and do not need to make any changes to the functionality implemented by the subsequent product. The biggest advantage of the simple factory model is that the workshop mode contains the necessary judgment logic, which can generate the products that the customer needs according to the customer's demand, and in the aspect of the customer, it eliminates the customer's reliance on the specific product creation, in a word: The simple workshop realizes the division of responsibility.
Said the advantage again to say disadvantage, if now add a new product called PRODUCTC how to do? OK, we add Class PRODUCTC, implement IProduct interface (note, this is due to the changes brought by the new business rules, is unavoidable in any mode), the following is the need to let our simple factory has the ability to produce this new product, how to achieve? You naturally think that adding a case statement is not over? But it's not as simple as adding a case statement that means you've modified the factory class itself-violating the most important OCP principle of design principles. The open closure principle requires avoiding the direct modification of the class and extending the functionality of the class through inheritance. In addition, too many case statements can easily confuse logic, resulting in the stability of the factory class decline. So how can the new product increase be handled properly and not violate the design principles? So-the factory approach (Factory method) appeared.

Also talk about factory methods

Let's take a look at the class diagram of the factory approach (Factory method):

Factory methods are generally implemented in the following ways:

public Interface Ifactory


{


iproduct createproduct ();


}


///


///specializes in manufacturing producta plants


///


public class Productafactory:ifactory


{


public iproduct createproduct ()


{


return new ProductA ();


}


}


///


///specializes in manufacturing PRODUCTB plants


///


public class Productbfactory:ifactory


{


public iproduct createproduct ()


{


return new PRODUCTB ();


}


}

Let's take a look at the response strategy for the new product PRODUCTC, the factory approach model. The first is still to add a new class PRODUCTC, and then add the factory class Productcfactory to produce the new product and implement the Ifactory interface, so that you can instantiate the new product without modifying the existing code ... Perfect? Don't worry, we'll take a look at the client's code:

public class Client


{


public void Do ()


{


//create a producta


Ifactory factory = new Productafactory ();


//ifactory factory = new Productbfactory ();





IProduct Product = Factory. Createproduct ();


product. DoTask1 ();


product. DoTask2 ();


product. DoTask3 ();


product. DoTask4 ();


product. DoTask5 ();


//do More Tasks


}


}

At this point, you will find that the client needs to decide which factory to instantiate to produce the product that it needs, and the logic of judgment still exists, only from the internal logical judgment of the simple factory to the client code for logical judgment. That is to say, if you want to eventually produce a PRODUCTC still need to modify the code, but only the location of this change moved to the client!

Coping strategies, many people know that an effective solution to this problem is available. NET's reflection characteristics or other IOC mechanisms by writing the factory class name that needs to be instantiated into the configuration file, read through reflection, and the code reads as follows:

<appSettings>


<add key= "factoryname" value= productbfactory "/>"


<appSettings>

public class Client


{


public void Do ()


{


string factoryname = configurationsettings.appsettings["Factoryname"];


Ifactory factory = (ifactory) assembly.load ("Factory method"). CreateInstance (


"Factory_method." + factoryname);


iproduct Product = Factory. Createproduct ();


product. Dotask ();


}


}

This is almost a perfect coping strategy for object creation, however ....

New questions

There are "good things" to put forward, since all use. NET reflection mechanism is there any need for the factory class itself? Is it possible to omit the steps of the factory production by writing the product name that needs to be produced in the compounding file directly reflecting the specific product instance? Specific code references are as follows:

iproduct Product = (iproduct) assembly.load ("Factory method")


    . CreateInstance ("Factory_method." + productName);


product. Dotask ();

For this question, although it seems that he has a certain simplification in the code but I think he ignores another feature of the factory model, which encapsulates the creation of objects, and reflects the reusability of the code.

Let's compare two pieces of code without using the factory:

iproduct product1 = (iproduct) assembly.load ("Factory method")


    . CreateInstance ("Factory_method." + productName);


Product1. Dotask ();





iproduct product2 = (iproduct) assembly.load ("Factory method")


    . CreateInstance ("Factory_method." + productName);


Product2. Dotask ();





iproduct product3 = (iproduct) assembly.load ("Factory method")


    . CreateInstance ("Factory_method." + productName);


Product3. Dotask ();

Use of the factory:

Ifactory factory = (ifactory) assembly.load ("Factory method")


  . CreateInstance ("Factory_method." + factoryname);





iproduct Product1 = Factory. Createproduct ();


Product1. Dotask ();





iproduct product2 = Factory. Createproduct ();


Product2. Dotask ();





iproduct product3 = Factory. Createproduct ();


Product3. Dotask ();


You can see that code snippets that don't use factory methods are flooded with similar (iproduct) assembly.load ("Factory method"). CreateInstance ("Factory_method." + productName) code, first of all, it is not elegant, followed by the reuse of code, if the project's assembly name or namespace has changed? Although this situation rarely happens in actual projects, you can consider how many places you need to modify if this happens. So this is the final solution, and it seems to me that the factory approach (Factory method) is still debatable.

First, the logic is relatively complex and difficult to use. Is it possible for everyone to skillfully use the factory method model in the project?

Second, we can see that every time we add a new product type, we need to increase the number of factories that produce the product, which leads to a workload outside the business requirements. Below ....

New Solutions

Using the reflection mechanism mentioned in section III, I pondered whether the reflection mechanism could be combined with a simple factory, still with the simple factory design pattern, and the logic of its judgment on the product changed from the original code to the reflection configuration file. The following code is first referenced.

Improved Simple factory:

public class Improvedfactory


{


public static iproduct createproduct ()


{


string productName = configurationsettings.appsettings["ProductName"];


iproduct Product = (iproduct) assembly.load ("Factory method")


      . CreateInstance ("factory_method.improvement." + productName);


return product;


}


}

Ok, let's look at the client code again:

iproduct Product = Improvedfactory.createproduct ();


product. Dotask ();

The same is true for new product productc, what kind of work should be done?

A to add class PRODUCTC and implement the IProduct interface, as I said earlier, this is a change that cannot be avoided with any pattern.

b Add more information about PRODUCTC to the configuration file.

You see that? There are not so many complex abstractions, concrete factories, no new factories to add to new products, no need to modify the factory class itself or client code; Just two steps above to complete a new product add and create work.

The above is my attempt to a kind of new solution, perhaps this kind of plan also has the flaw place, but I have not thought the concrete flaw to have which, just contact the design pattern soon, many ideas are not mature enough, also hoped that the teacher predecessors to add the guidance.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.