Learn Bridge design mode from the perspective of reconstruction
Bridge mode is a mode that is often used in actual systems. It can best reflect the principle of design patterns
Programming for the interface, and use aggregation without inheriting these two principles.
Since we are overloaded, make the structure of the class is too complicated, it is difficult to understand, it is difficult to maintain. especially
It is in Java because it cannot inherit multiple classes at the same time, this will cause multiple layers and more difficult to maintain.
The Bridge mode is the root cause of multiple layers of inheritance. If you implement a class in your application, you need to inherit
Two or more classes, and there is a certain relationship between the two, each of them will change.
Bridge mode is to decompose these two classes into an abstraction, an implementation, so that they separate, so
Two categories can be independently changed.
Abstract is, take the common concept of an entity (the same step), draw out (decompose several independent steps),
As a process. As we put the database's operation abstraction, there are several steps to create a SQL statement.
Send to the database processing, achieve the result.
How to complete this abstraction step, such as sending to the database, need to combine specific databases, consider how to complete this step.
And the same step may have different implementations, such as different implementations for different databases.
Now we assume a situation, and it is often encountered in the web, and there is a input box in a page.
If the name, address, etc. of the customer information, after entering the information, then press the Find button to display the results of the lookup.
We now assume that the customer information and account information are found, they are in different tables.
But our system faces two people, and their information is saved to Oracle database, but each branch is
The data saved in Sybase, the location of the database is different, and the two operations are different.
Below is the way we usually use, use if Else, judgment, so that the system is used
It is difficult to maintain, it is difficult to expand, may you add a query, or a database trial? ? ? ?
Public class searchaction () {
Public Vector SearchData (String ActionType, String DBTYPE) {
String SQL = "";
IF (ActionType.equal) {
// If you are querying customer information, spelling a SQL statement reads data from the client table
SQL = "SELECT * FROM CUSTOMER"
IF (DBTYPE.EQUAL ("Oracle")) {
// Read from the headquarters database, the database is Oracle
String connect_string = "JDBC: Oracle: Thin: HR / HR @ localhost: 1521: hrdb";
Drivermanager.RegisterDriver (New Oracle.jdbc.OracleDriver ());
Connection conn = drivermanager.getConnection (connect_string);
// Create a Statement
Statement Stmt = conn.createstatement ();
ResultSet Rset = Stmt.executeQuery (SQL);
/ / The following is omitted to remove data from the database, assemble it into a vector, return
................................................ ...................
} else (DBTYPE.EQUAL ("Sybase")) {
// Read from the branch database, the database is Sybase
String connection_string = "JDBC: Sybase: TDS: CAI/cai@192.168.1.12: 1521: fin";
Drivermanager.RegisterDriver (new com.sybase.jdbc.sybdriver ());
Connection conn = drivermanager.getConnection (connect_string);
// Create a Statement
Statement Stmt = conn.createstatement ();
ResultSet Rset = Stmt.executeQuery (SQL);
/ / The following is omitted to remove data from the database, assemble it into a vector, return
................................
.................................
}
} else if (ActionType.Equal) {
// If you are query account information, splicing the SQL statement reads the data from the account table
SQL = "SELECT * ACCOUNT"
IF (DBTYPE.EQUAL ("Oracle")) {
..........................
..........................
(Author Note: This is omitted from Oracle, about 300 words)
} Else IF (DBTYPE.EQUAL ("Sybase")) {
..........................
..........................
(Author Note: This is omitted from Sybase, about 300 words)
}
}
}
}
If you think this is a relatively mentally handicap, you should use a function, but you will use if else.???
So we reimburse it, first we have learned DAO model, which is to read the data, we define one
Common interface, it is responsible for the operation of the database, then implementation according to different databases, in our query operation,
Use the interface to operate so that we can implement the process without considering the specific implementation.
Query the joint interface:
Public interface searchdb {
Public Vector SearchFromDB (String SQL)
}
Oracle database query implementation
Public class searchdboracleImpl {
Public Vector SearchFromDB (String SQL) {
// Read from the headquarters database, the database is Oracle
String connect_string = "JDBC: Oracle: Thin: HR / HR @ localhost: 1521: hrdb";
Drivermanager.RegisterDriver (New Oracle.jdbc.OracleDriver ());
ResultSet Rset = Stmt.executeQuery (SQL);
.............................
..............................
}
}
Sybase database query implementation
Public class searchdbsysbaseImpl {public vector searchfromdb (string sql) {
// Read from the branch database, the database is SYSBASE
String connection_string = "JDBC: Sybase: TDS: CAI/cai@192.168.1.12: 1521: fin";
Drivermanager.RegisterDriver (new com.sybase.jdbc.sybdriver ());
ResultSet Rset = Stmt.executeQuery (SQL);
.............................
..............................
}
}
This allows you to use interface SearchDB in our query, but create a problem because we can't
Static determination, the database type of queries must be dynamically determined, so we think of using simple factory methods,
To create specific implementations here, create according to categories
Public class searchfactory {
Public Static SearchDB Createsearch (int dbtype) {
IF (DBTYPE.EQUAL ("Oracle")) {
Return SearchDBoracleImpl ();
} Else IF (DBTYPE.EQUAL ("Sybase")) {
Return SearchDBSYSBaseImpl ();
}
}
}
So our query code can be changed to this;
Public class searchaction () {
Public Vector SearchData (String ActionType, String DBTYPE) {
String SQL = "";
IF (ActionType.equal) {
// If you are querying customer information, spelling a SQL statement reads data from the client table
SQL = "SELECT * FROM CUSTOMER"
SearchDB obj = searchfactory.createsearch (dbtype);
Return Obj.SearchFromDB (SQL);
} else if (ActionType.Equal) {
// If you are query account information, splicing the SQL statement reads the data from the account table
SQL = "SELECT * ACCOUNT"
SearchDB obj = searchfactory.createsearch (dbtype);
Return Obj.SearchFromDB (SQL);
}
}
}
Is it simple, if you add a new database, you can implement it for us to add a new database.
The old code does not need to change, so that the opening-closed principle (Open-Closed principle), in our query
Used in the interface, this is the principle of design mode, programming the interface, and uses aggregation, not direct inheritance
Everyone can consider using inheritance to complete how this work is achieved? ? ? ? ?
The above is to separate the implementation, and achieve dynamic changes! ! ! ! !
We separate the specific database implementation of the inquiry operation, enhance flexibility, but our query.
It is still not easy to expand in this still use of IF Else, so we have the process of abstract a query operation, divide it into several specific steps, create SQL statements, send it to the database, execute queries, return the result.
Although they are different queries, SQL varies, different databases are different, and the contents of return results are different. but
This process is constant, so we declare an abstract class to complete this process.
Public Abstract Class search {
SearchDB Obj;
// Two steps
Public SearchDB CreatesearchImple (int dbtype) {
Return SearchFactory.createSearch (dbtype);
}
Public Abstract string createSQL ();
// Query process, final return result
Public Vector SearchResult (int DBTYPE) {
Obj = createsearchImple (DBTYPE);
Return Obj.SearchFromDB (Createsql ())
}
}
// Our customer query, operation
Public class searchCustomerction {
Public string createsql () {
Return "SELECT * from Customer"
}
}
// Our account query operation
Public class seat search {
Public string createsql () {
Return "SELECT * ACCOUNT"
}
}
So our query programming simple creation SQL statement, we should create a factory method,
To complete the creation
Public class actionFactory {
Public Static Searchaction CeateAction (Int ActionType) {
IF (ActionType.equal ("Customer")) {
Return SearchCustomraction ();
} else if (ActionType.equal ("Account")) {
Return searchaccountaction ();
}
}
}
In this way, we have abstracted the process of query operations, define steps, and specific processes, through our twice
Separate abstract parts and achievements so that they can change independently, enhance flexibility.
We look at the realization of the original query, now it has been modified twice, what is the way? as follows:
Public class searchaction () {
Public Vector SearchData (String ActionType, String DBTYPE) {
SEARCHACTION Action = ActionFactory.ceate;
Return Action.SearchResult (dbtype);
}
Now if you add a database type, will it change? ? If you add a query action to change those? ? ?
Discussion point:
1: During our reconstruction process,
How to use design model principles? ? ?
Now if you increase your function, follow the principle of opening and closing? ?
2: We used two simple factories, this is to simplify, generally best to use abstract factory methods.
If you change to an abstract factory, how to modify it? ? ?
I intend to write a series of articles to introduce design patterns,
I hope to consider the model's application from the perspective of the reconstruction, not
Direct introduction mode, this is easy to get started with beginners, Step by step.
If you encounter similar scenarios in your own code, you can reconstruct it.
Recipient learning proxy, notice
Why is the three roles of Home, Remote, Bean?
Why is the client interact with the container? ?
Describes the application in EJB? ? ?
Learn Decorator ??