Design Patterns (3) -- Abstract Factory patterns (Absrtact Factory Pattern), absrtactpattern

Source: Internet
Author: User

Design Patterns (3) -- Abstract Factory patterns (Absrtact Factory Pattern), absrtactpattern

Definition

The essence of the abstract factory mode is to provide interfaces to create a series of related or independent objects without specifying the specific classes of these objects.

Understanding

In software systems, there are often "a series of mutually dependent objects". At the same time, due to changes in requirements, there are often more series of objects to be created. How to deal with this change? How to bypass the conventional object creation method (familiar with the new operator) and provide an "encapsulation mechanism" to avoid the tight coupling between customer programs and such "Multi-series object creation work? This is the abstract factory model we want to talk about. The abstract factory model provides a way to encapsulate a group of independent factories with the same topic. In normal use, the client program needs to create the specific implementation of the abstract factory, and then use the abstract factory as an interface to create the specific object of this topic. The client program does not need to know (or care about) the specific types of objects it obtains from these internal factory methods, because the client program only uses the common interfaces of these objects. The abstract factory mode separates the implementation details of a group of objects from their general usage.

Structure

Advantages

Disadvantages

Applicable situations

Code example

(The TerryLee example and code are used here)

Chinese enterprises need a simple financial calculation: at the end of each month, financial personnel need to calculate employees' salaries.

Employee Salary = (basic salary + bonus-personal income tax ). This is an algorithm that is accurate to all corners of the world.

To simplify the system, we assume that the basic salary of employees is always USD 4000.

The calculation rules of China Enterprise bonus and personal income tax are as follows:

Bonus = basic salary (4000) * 10%

Personal Income Tax = (basic salary + bonus) * 40%

We need to build a software system (codenamed Softo) to meet the needs of Chinese enterprises.

In this case, the simplest method is used. The class diagram is as follows:

The Code is as follows:

Using System; namespace ChineseSalary {// <summary> // Calculate China's Personal Income Tax // </summary> public class ChineseTax {public double Calculate () {return (Constant. BASE_SALARY + (Constant. BASE_SALARY * 0.1) * 0.4 ;}} using System; namespace ChineseSalary {// <summary> // Calculate the Chinese individual bonus /// </summary> public class ChineseBonus {public double Calculate () {return Constant. BASE_SALARY * 0.1 ;}}} namespace ChineseSalary {// <summary> // public Constant /// </summary> public class Constant {public static double BASE_SALARY = 4000 ;}} using System; namespace ChineseSalary {// <summary> // client program call // </summary> public class Calculator {public static void Main (string [] args) {ChineseBonus bonus = new ChineseBonus (); double bonusValue = bonus. calculate (); ChineseTax tax = new ChineseTax (); double taxValue = tax. calculate (); double salary = 4000 + bonusValue-taxValue; Console. writeLine ("Chinaese Salary is:" + salary); Console. readLine ();}}}

The salary calculation for American enterprises is roughly the same as that for China, but the calculation rules for bonus and personal income tax are different from those for China:

Bonus = Basic Salary * 15%

Personal Income Tax = (basic salary * 5% + bonus * 25%)

We only change ChineseTax and ChineseBonus to AmericanTax and AmericanBonus. Only the name of the partial category and the content of the class method have been modified, and the structure has not changed. The modified class diagram is as follows:

The Code is as follows:

Using System; namespace AmericanSalary {// <summary> // Calculate the U.S. personal bonus /// </summary> public class AmericanBonus {public double Calculate () {return Constant. BASE_SALARY * 0.1 ;}} using System; namespace AmericanSalary {// <summary> // Calculate the U.S. Personal Income Tax // </summary> public class AmericanTax {public double Calculate () {return (Constant. BASE_SALARY + (Constant. BASE_SALARY * 0.1) * 0.4 ;}} using System; namespace AmericanSalary {// <summary> // public Constant /// </summary> public class Constant {public static double BASE_SALARY = 4000 ;}} using System; namespace AmericanSalary {// <summary> // client program call // </summary> public class Calculator {public static void Main (string [] args) {AmericanBonus bonus = new AmericanBonus (); double bonusValue = bonus. calculate (); AmericanTax tax = new AmericanTax (); double taxValue = tax. calculate (); double salary = 4000 + bonusValue-taxValue; Console. writeLine ("American Salary is:" + salary); Console. readLine ();}}}

At first, we only want to run the Softo System on Chinese enterprises. But as MaxDO's business expands overseas, MaxDO needs to port the system to the United States. We need to integrate the above two situations in China and the United States into one system. During the migration, MaxDO had to discard the business rule classes ChineseTax and ChineseBonus of Chinese enterprises, and then created two new business rule classes for American enterprises: AmericanTax and AmericanBonus. Finally, the Calculator class is called for business rules.

As a result, we found that the original class is discarded every time the Softo system is transplanted. Now, If Huawei wants to purchase this system, we have to abandon AmericanTax and AmericanBonus and modify the original business rules. One immediate thought is to retain all business rule models in the system, that is, to retain wage calculation rules for Chinese and American enterprises.

The integration problem of the previous system is that the Caculator code still needs to be modified when the customer switches between the United States and Chinese enterprises.

A well-maintained system should follow the "open and closed principle ". That is, to close the modification to the original code and open the extension to the original code (such as class inheritance and interface implementation)

We found that both Chinese enterprises and American enterprises use the same computing interface for their business operation rules. As a result, it is natural to create two business interface classes Tax and Bonus, and then let AmericanTax, AmericanBonus and ChineseTax and ChineseBonus implement these two interfaces respectively. The class diagram is as follows:

The Code is as follows:

Using System; namespace InterfaceSalary {// <summary> // Bonus abstract class /// </summary> public abstract class Bonus {public abstract double Calculate ();}} using System; namespace InterfaceSalary {// <summary> // Calculate the Chinese personal Bonus /// </summary> public class ChineseBonus: Bonus {public override double Calculate () {return Constant. BASE_SALARY * 0.1 ;}} using System; namespace InterfaceSalary {// <summary> // Personal Income Tax abstract class // </summary> public abstract class Tax {public abstract double Calculate () ;}} using System; namespace InterfaceSalary {// <summary> // Calculate China's Personal Income Tax // </summary> public class ChineseTax: Tax {public override double Calculate () {return (Constant. BASE_SALARY + (Constant. BASE_SALARY * 0.1) * 0.4 ;}} using System; namespace InterfaceSalary {// <summary> // public Constant /// </summary> public class Constant {public static double BASE_SALARY = 4000 ;}} using System; namespace InterfaceSalary {// <summary> // client program call // </summary> public class Calculator {public static void Main (string [] args) {Bonus bonus = new ChineseBonus (); double bonusValue = bonus. calculate (); Tax tax = new ChineseTax (); double taxValue = tax. calculate (); double salary = 4000 + bonusValue-taxValue; Console. writeLine ("Chinaese Salary is:" + salary); Console. readLine ();}}}

However, the interfaces added above hardly solve any problem, because the Caculator code still needs to be modified when the system customers switch between the US and Chinese enterprises. There are only two missing modifications, but you still need to modify the ChineseBonus and ChineseTax sections. The fatal problem is that we need to transfer this porting job to a software company called Hippo. Due to copyright issues, we did not provide the source code of the Softo system to Hippo companies. Therefore, Hippo companies cannot modify Calculator at all, leading to the failure of transplantation.

To this end, we want to add a tool class named Factory. The Code is as follows:

Using System; namespace FactorySalary {// <summary> // Factory class /// </summary> public class Factory {public Tax CreateTax () {return new ChineseTax ();} public Bonus CreateBonus () {return new ChineseBonus ();}}}
The modified client code:
Using System; namespace FactorySalary {// <summary> // client program call /// </summary> public class Calculator {public static void Main (string [] args) {Bonus bonus = new Factory (). createBonus (); double bonusValue = bonus. calculate (); Tax tax = new Factory (). createTax (); double taxValue = tax. calculate (); double salary = 4000 + bonusValue-taxValue; Console. writeLine ("Chinaese Salary is:" + salary); Console. readLine ();}}}

Yes, we have solved a big problem. Imagine what we need to do now when the system is migrated from a Chinese enterprise to an American enterprise?

The answer is: we don't need to do anything for the Caculator class. We need to modify the Factory class.

Obviously, the preceding solution brings a side effect: the system not only adds new Factory classes, but also only migrates the job to the Factory class when the system is transplanted, the workload has not been reduced, and the source code of the system needs to be modified. We can see from the changes made to the Factory class during system migration: in fact, it belongs to American enterprises or Chinese enterprises. The name should be called AmericanFactory, which is more suitable for ChineseFactory.

The solution is to add an abstract factory class AbstractFactory and add a static method based on a configuration file (App. config or Web. config) an item (such as factoryName) dynamically determines which factory class should be instantiated. In this way, we will transfer the porting work to modifying the configuration file. The modified class diagram is as follows:

The code for the abstract factory class is as follows (using the reflection mode ):

Using System; using System. reflection; namespace AbstractFactory {// <summary> // Factory class /// </summary> public abstract class AbstractFactory {// public AbstractFactory GetInstance () // {// string factoryName = Constant. STR_FACTORYNAME.ToString (); // AbstractFactory instance; // if (factoryName = "ChineseFactory") // instance = new ChineseFactory (); // else if (factoryName = "AmericanFactory") // I Nstance = new AmericanFactory (); // else // instance = null; // return instance; //} public AbstractFactory GetInstance () {string factoryName = Constant. STR_FACTORYNAME.ToString (); AbstractFactory instance; if (factoryName! = "") Instance = (AbstractFactory) Assembly. load (factoryName ). createInstance (factoryName); else instance = null; return instance;} public abstract Tax CreateTax (); public abstract Bonus CreateBonus ();}}

The configuration file is as follows:


Java Abstract Factory Mode

The factory model is often used in projects. Some people say that only large projects can be used, but small projects cannot be used. in fact, there is no substantial link between the design model and the project size. the design model is a summary of experience rather than a standard to measure the project size.

Taking the DAO layer of the development project as an example, the customer's requirements in the project are often changed, and temporary database replacement needs also often occur. How should we solve the cross-database function, here we will use the abstract factory model. the factory mode is often used to create multi-series objects (such as Orale series and MySql series)

1. Define related interfaces first (no difference from common practices)

Java code
// Role table DAO Interface
Interface IroleDao {
Void insert ();

Void update ();
}
// User table DAO Interface
Interface IuserDao {
Void find ();

Void delete ();
}

// Role table DAO Interface
Interface IroleDao {
Void insert ();

Void update ();
}
// User table DAO Interface
Interface IuserDao {
Void find ();

Void delete ();
} 2. Different databases have different SQL statements. Therefore, they must be implemented in different databases.

Java code
// User table Oralce database DAO
Class OracleuserDao implements IuserDao {
Public void delete (){
System. out. println ("Oralce deletes User table data ");
}

Public void find (){
System. out. println ("Oralce queries User table data ");
}
}

// User table MySql database DAO
Class MySqluserDao implements IuserDao {
Public void delete (){
System. out. println ("MySql deletes user data ");
}

Public void find (){
System. out. println ("MySql user data query ");
}
}
// Role table Oracle Database DAO
Class implements leroledao implements IroleDao {
Public void insert (){
System. out. println ("Oralce inserts data into the role table ");
}

Public void update (){
System. out. println ("Oracle updating role table data ");
}
}

// Role table MySql database DAO
Class MySqlrole... the remaining full text>

What are the design patterns?

There are three types of design patterns: creation, structure, and behavior.
The creation types include:
I. Singleton, Singleton mode: ensure that a class has only one instance and provide a global access point to it.
2. Abstract Factory: provides an interface for creating a series of related or mutually dependent objects without specifying their specific classes.
3. Factory Method: Define an interface used to create objects, and let the subclass decide which class to instantiate. Factory Method delays the instantiation of a class to the subclass.
4. Builder: separates the construction of a complex object from its representation, so that different representations can be created during the same construction process.
5. Prototype: Use a Prototype instance to specify the type of the object to be created, and copy the Prototype to create a new object.
Behavior types:
6. Iterator: provides a method to access each element of an aggregate object sequentially without exposing the internal representation of the object.
7. Observer: Observer mode: defines one-to-many dependencies between objects. When the status of an object changes, all objects dependent on it will be automatically updated by notification.
8. Template Method: defines the skeleton of an algorithm in an operation, and delays some steps to the subclass, templateMethod allows the subclass to redefine a specific step without changing the structure of an algorithm.
9. Command: encapsulate a request as an object so that you can parameterize the customer with different requests, queue requests and record request logs, and supports unrecoverable operations.
10. State: allows an object to change its behavior when its internal State changes. The object seems to have changed its class.
11. Strategy: Define a series of algorithms, encapsulate them one by one, and enable them to replace each other. This mode allows algorithms to be independent of customers who use them.
12. China of Responsibility, Responsibility chain mode: Enables multiple objects to process requests to avoid coupling between the request sender and receiver.
13. Mediator: uses an intermediary object to encapsulate object interaction of some columns.
14. Visitor, Visitor mode: indicates an operation that acts on each element in an object structure. It allows you to define new operations that act on this element without changing the element classes.
15th, Interpreter, Interpreter mode: a language is defined to define a representation of its grammar and an Interpreter. This Interpreter uses this representation to explain sentences in the language.
16. Memento: capture the internal state of an object without interrupting the object, and save the state outside the object.
There are:
17. Composite: Composite combines objects into a tree structure to represent the relationship between parts of the whole. Composite makes the use of a single object and a Composite object consistent.
18. Facade, appearance mode: provides a consistent interface for a group of interfaces in the subsystem. fa? Ade provides a high-level interface, which makes the subsystem easier to use.
19. Proxy: provides a Proxy for other objects to control access to this object.
20. Adapter: the Adapter mode converts a class of interfaces into another interface that the customer wants. The Adapter mode makes those classes unable to work together due to interface incompatibility.
21. Decrator: the Decorator mode dynamically adds some additional responsibilities to an object. In terms of the added functions, the Decorator mode is more flexible than the subclass generation mode.
22. Bridge: link the abstract Part with its implementation... the remaining full text>

Related Article

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.