Review design patterns (5)-What I understand as "Abstract Factory"

Source: Internet
Author: User
Tags oracleconnection

Read this articleArticleBefore that, I would like to remind you that my article may not be referred to as a design pattern article. It can only be regarded as a design summary in my project. Here, I welcome everyone to discuss it with me. At the same time, I want to say that the purpose of my blog writing is to remind others of my experience. However, if the opposite effect is caused, it is against my original intention, so I hope you can think about my point of view and think about it again! In addition, I would like to thank Jack. Net for assembling his head and giving me some encouragement.

1.CodeIntroduction

Let's use a piece of code to introduce this article.

Believe everyone, whether B/S or C/S. It is inevitable to deal with databases. Such code is common:

Static voidMain (String[] ARGs ){StringConnectionstring =".........";SqlconnectionThisconnection =NewSqlconnection(Connectionstring );StringCommandstring ="Select * from";Using(Thisconnection) {thisconnection. open ();SqlcommandThiscommand =NewSqlcommand(Commandstring, thisconnection); thiscommand. executenonquery ();}}

Such code is not controversial at ordinary times and runs well.

However, I have encountered such a situation in the company. The customers say that they think SQL server is not good and cannot meet any requirements. Although he is talking about the paradox, but we must also meet the customer's needs.

Then, replace the Oracle database as required. However, it is found that the workload is very large. The list is lost.

Where is the error?

2. How to modify it?

 
StringConnectionstring ="............."; Oracleconnection thisconnection =NewOracleconnection (connectionstring );StringCommandstring ="Select * from";Using(Thisconnection) {thisconnection. open (); oraclecommand thiscommand =NewOraclecommand (commandstring, oracleconn); thiscommand. executenoquery ();}

Every place, we need to change the code to this, I know, inProgramThe code that involves database operations is everywhere. Such a large amount of work can not be completed in a short time. More importantly, an operation may be terminated due to omissions .........

3. Extract Abstract Factory

I have never figured out what the name means. Why is it an abstract factory ??

We will not discuss this issue. Step into the formal topic, let's see what is an abstract factory and what is its purpose?

Provides an interface for creating a series of related or mutually dependent objects without specifying their specific classes.

Next, let's take a look at his UML diagram:

4. Product Family

When a colleague asks me the meaning of the abstract factory, I always give him the word "Product Family.

In today's society, few companies create their own products.

A car may be a Chinese shell, an American engine, Japanese paint, German glass, etc.

Then we will call this set, Shell, engine, paint, and glass as a product family.

5. Horizontal and vertical

Next, let's analyze the differences between the horizontal and vertical directions.

In fact, this is also the type of abstract factory and factory methods to solve the problem.

What is landscape. A tree is a horizontal relationship between leaf nodes under the same parent node, that is, the sibling nodes.

What about vertical lines? Different root nodes, but they will eventually be combined, so we call this relationship vertical.

For example, an American engine is a Chinese shell. They are a class inherited from the engine, a class inherited from the shell, not a sibling node, but they will eventually be combined, so we call them vertical relationships.

We can also find that the horizontal direction is absolute and the vertical direction is relative.

China's glass and Japanese glass, in any case, all of them inherit from glass and are horizontally related.

But for the US engine in the Chinese shell, if one day a car is built and he does not need the engine, then the vertical relationship between them will be canceled.

6. Small application of Abstract Factory

Although I tried my best to find an example that is not so cheesy, I still could not be refined.

Use a computer for example.

 Class  Program { Static void Main ( String [] ARGs ){ Abstractfactory Factory = New  Factory1 (); CPU CPU = factory. createcpu (); Graphics Graphics = factory. creategraphics (); CPU. dosomething (); graphics. dosomething ();}} /// <Summary> /// Various CPUs  /// </Summary>  Abstract class  CPU {} Class  Intelcpu : CPU {} Class  Amdcpu : CPU {} /// <Summary> ///  Various graphics cards  /// </Summary>  Abstract class  Graphics {}Class  Atigraphics : Graphics {} Class  Gforcegraphics : Graphics {} /// <Summary> ///  Various abstract factories  /// </Summary>  Abstract class  Abstractfactory { Public Abstract  CPU Createcpu (); Public Abstract Graphics Creategraphics ();} Class  Factory1 : Abstractfactory { Public override  CPU Createcpu (){ Return new  Amdcpu ();} Public override  Graphics Creategraphics (){ Return new  Atigraphics ();}} Class Factory2 : Abstractfactory { Public override  CPU Createcpu (){ Return new  Intelcpu ();} Public override  Graphics Creategraphics (){ Return new  Gforcegraphics ();}}

A vertical combination of CPU and video card, each type of CPU can be freely combined with each type of video card, so here we use the abstract factory mode to complete their overall combination relationship.

7. Abstract Factory. Net Applications

Here, we will go back to the problem of our database in the article.

In. NET Framework, the namespace system. Data. Common is provided for us;

This namespace contains classes shared by various. NET Framework data providers. It is designed to provide developers with a way to write ADO. Net code that will act on all. NET Framework data providers.

We try to use this method to transform the above Code:

Static voidMain (String[] ARGs ){DbproviderfactoryFactory =Dbproviderfactories. Getfactory ("System. Data. sqlclient");DbconnectionThisconnection = factory. createconnection ();StringCommandstring ="Select * from";Using(Thisconnection) {thisconnection. open ();DbcommandThiscommand = factory. createcommand (); thiscommand. commandtext = commandstring; thiscommand. Connection = thisconnection; thiscommand. executenonquery ();}}

At this time, we can say that your database operations are decoupled from specific databases.

However, we still need to modify the code at N points during the modification. Because you need to change system. Data. sqlclient to system. Data. oracleclient at each call.

What should we do?

8. Abstract Factory + configuration file

Configuration files are very useful. After each configuration file is modified, the entire project no longer needs to go through the painful compilation process.

Then we can write the changed part into the configuration file.

This is also common in many design ideas.

I will not write the code here. The idea is probably:

<Add key = "SQL Server" value = "system. Data. sqlclient">

Then, we can call the value of this configuration file instead of writing the specific string to the code.

9. Abstract Factory + simple factory

Let's review what the simple factory has solved?

A simple factory isolates the creation process of an object from the client, and encapsulates the creation of an object in a factory.

In the above Code, we will create dbproviderfactory and take it to a simple factory for implementation:

 Static class  Simplefactory { Public  Dbproviderfactory Getfactory ( String Dbname ){ Switch (Dbname ){ Case  "SQL Server" : Return  Dbproviderfactories . Getfactory ( "System. Data. sqlclient" ); Break ; Case  "Oracle" : Return  Dbproviderfactories . Getfactory ("System. Data. oracleclient" ); Break ; Default : Return  Dbproviderfactories . Getfactory ( "System. Data. oledb" );}}}

10. It seems that the origin is returned.

At this time, many people will say, aren't you going back to the origin? You used dbproviderfactory to avoid modification on N clients, but in this case, I need to modify the incoming dbname on each client.

OK. No problem!

Let's continue to improve the program. In the previous article: Review design model (iv) -- factory model, I proposed a simplified factory.

We will rewrite the simplefactory above:

Static classSimplefactory{PublicDbproviderfactoryGetfactory (){ReturnDbproviderfactories. Getfactory ("System. Data. sqlclient");}}

Then we encapsulate this simple factory in a single DLL. Then, if we need to change the database connection, we only need to modify this DLL. Take one breath and move the whole body.

Is it perfect?

11. Simple factory vs. Simplified Simple Factory

Many people will say, if this is the case, what is the purpose of a simple factory?

Let's take this into consideration. If we use two sets of databases, Oracle and SQL Server, in a project, how do you solve this problem?

You can only return a fixed factory. In this case, the requirements cannot be well met.

Therefore, your design depends on your actual situation. Do not design it or overdesign it.

12. Class explosion

In my previous articles, I used object explosion many times. Here, I want to propose a new word called class explosion.

What is a class explosion. We also use the following computer example to talk.

Intel CPU, amd cpu, ATI graphics card, gforce graphics card, two sets of horizontal relationships, each group of horizontal relationships has two elements, so it is a combination of 2*2 = 4, what if there are 10 horizontal links in each group with 10 elements? Then we need 10x10 abstract factories, and we know that the role of the abstract factory is only to help us build this composite object.

What should we do? What should I do? What should I do?

13. Transform the Abstract Factory

As we have seen before, if you specify an abstract factory for each product, it will inevitably lead to a class explosion in the abstract factory.

So how can we improve it?

We can see that the number of vertical products in each Abstract Factory is fixed. What they are different is the choice of horizontal products.

Then we will add the horizontal products we want to select.

 Class  Abstractfactory { Private string Cputype; Private string Graphicstype; Public Abstractfactory ( String Cputype, String Graphicstype ){ This . Cputype = cputype; This . Graphicstype = graphicstype ;} Public  CPU Createcpu (){ Type T = Type . GetType (cputype ); Return ( CPU ) Activator . Createinstance (t );} Public  Graphics Crategraphics (){Type T = Type . GetType (graphicstype ); Return ( Graphics ) Activator . Createinstance (t );}}

Then we write in the client like this:

Static voidMain (String[] ARGs ){AbstractfactoryFactory =NewAbstractfactory("Intercpu","Atigraphics");CPUCPU = factory. createcpu ();GraphicsGraphics = factory. crategraphics ();}

Of course, we can encapsulate the new factory process into a unified DLL.

I think someone will say at this time that this is not good. Isn't it equivalent to adding the coupling between the client and the product category?

This is very simple. We can use the configuration file to solve this problem.

No code is written here.

14. Limitations of the abstract factory

Let's continue to consider the example of the Computer above. It turns out that our computers have CPUs, graphics cards, and abstract factories. We can flexibly configure the hardware devices of our computers.

However, we imagine that if one day a keyboard is added to a computer, it may be Microsoft or IBM. What should we do?

We need to add a keyboard class and then add two subclasses. In addition, we also need to modify the class of the abstract factory.

If we use a classic abstract factory, we may need to modify tens of thousands of abstract factories.

What should I do? What should I do? What should I do?

15. Generic transformation Abstract Factory

Since the creation steps are the same, we will abstract the creation process. Of course, the method is generic.

 
ClassAbstractfactory{
 
Public staticT create <t> ()

 
{Return(T)Activator. Createinstance (Typeof(T ));}}

But how can we not expose the specific type to the client?

The method is that we provide a dictionary, and what we need to maintain is the dictionary.

We can choose to write this dictionary in the configuration file:

<Add key = "CPU" value = "intelcpu"/>

<Add key = "graphics" value = "atigraphics"/>

So we only need to call this method on the client:

 
Static voidMain (String[] ARGs ){CPUCPU =Abstractfactory. Create <Type. GetType ([CPU])> ();GraphicsGraphics =Abstractfactory. Create <Type. GetType ["Graphics"]> ();}

So when we add a keyboard, we only need to modify it in the configuration file, instead of understanding the thousands of abstract factories.

16. After the writing mode

In the above article, every transformation to the model is an improvement proposed by an individual under different circumstances.

Our learning model is to learn that design idea, and there is no need for this situation. I will follow the rules to write the corresponding classes and models according to the UML diagram, you can use your own improvement solution.

In every situation, we have a corresponding abstract factory in our hearts. What exactly is the abstract factory.

Gof provides us with a template, which is further designed by ourselves.

What is the design principle? What is the design pattern used?

They are good practice standards, but they are not common. Good things can satisfy our needs, and good designs can satisfy our needs and changes. At that moment, both design principles and design patterns are integrated into our hearts, and become empty.

In short, the design that complies with all design principles and design patterns is not necessarily a good design, but a proper violation is not necessarily a bad design, or even better or lighter. This is our purpose!

17. Factory Summary

A simple factory is the simplest factory and the most lightweight. It is equivalent to a network center, with all responsibilities on its shoulders. Once the factory crashes, the entire system crashes.

The factory method is the most moderate factory, and each factory encapsulates the creation process of a product.

Abstract Factory solves the problem of creating a product family. In abstract factory, we should pay attention to the horizontal and vertical concepts.

For different situations, we need to adopt different designs, factory models, abstract factories may not be better than simple factories, or even better than non-models.

18. Last piece of advice

A really good software designer, they don't apply every pattern, they have their own design strategy in their hearts, it is said that no knife wins.

The design pattern is stuck in front of the UML diagram of gof, where code is knocked and the pattern is pieced together. You can only say that you are still coding, and you are still far away from the design path.

Remember what the eternal path of building says: learn about him and forget him immediately.

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.