preface

Only a bald head can be strong

To recap:

  • Explain the agency model to your girlfriend
  • The packaging pattern is as simple as that
  • How many ways do you know how to write singleton?
  • Do you understand the factory model?

Design patterns are a must for both job interviews and personal promotion. Today we are going to explain the strategy pattern

I. Introduction of strategy mode

The first time I heard the term policy pattern was when I was learning JDBC. I don’t know if you’ve used DBUtils. At that time, fang Lixun asked us to encapsulate some common JDBC operations (actually imitating the DBUtils component).

The problem is this: We are going to encapsulate the query() method, passing in parameters such as String SQL, Object[] objects(specifying the SQL statement and corresponding parameters). We want to return different values for different businesses.

  • For example, sometimes we return a piece of data that we want to encapsulate as a Bean object
  • For example, sometimes we return multiple pieces of data, and we want to encapsulate these pieces of data into oneList<Bean>A collection of
  • For example, sometimes we return XXXX data, and we want to encapsulate this data into oneMap<Bean>A collection of
  • . Etc etc.

Here’s the solution:

  • Define an interface: ResultSetHandler(What does the caller want to do to the result set, simply by implementing this interface)
    • This interface defines the behavior.Object hanlder(ResultSet resultSet);
  • Then implement the interface above, for example, if we want to encapsulate a Bean object, that ispublic class BeanHandler implements ResultSetHandler
  • When you call it, it’s actuallyquery()The query method takes one more parameterquery(String sql, Object[] objects, ResultSetHandler rsh). The caller simply passes in the corresponding ResultSetHandler implementation class for whatever type it wants to return.

The code is as follows:

The query methods:// The return value of this method is arbitrary, so it is defined as Object.
    public static Object query(String sql, Object[] objects, ResultSetHandler rsh) {

        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;

        try {
            connection = getConnection();
            preparedStatement = connection.prepareStatement(sql);

            // Set the value of the SQL placeholder based on the parameters passed in
            if(objects ! =null) {
                for (int i = 0; i < objects.length; i++) {
                    preparedStatement.setObject(i + 1, objects[i]);
                }
            }


            resultSet = preparedStatement.executeQuery();

            // Calls the methods passed in by the caller to implement the class to operate on the result set
            returnrsh.hanlder(resultSet); } interface:/* * defines the interface to operate on the result set. What does the caller want to do to the result set, as long as the interface is implemented * */
    public interface ResultSetHandler {
         Object hanlder(ResultSet resultSet); } interface implementation class (Example) :// Interface implementation class that encapsulates the result set into a Bean object
	public class BeanHandler implements ResultSetHandler {
	
	
	    To encapsulate a Bean object, you first need to know what the Bean is, which is also passed in by the caller.
	    private Class clazz;
	
	    public BeanHandler(Class clazz) {
	        this.clazz = clazz;
	    }
	
	    @Override
	    public Object hanlder(ResultSet resultSet) {
	
	        try {
	
	            // Create an instantiation of the passed object
	            Object bean = clazz.newInstance();
	
	            if (resultSet.next()) {
	
	                // Get the result set metadata
	                ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
	
	                for (int i = 0; i < resultSetMetaData.getColumnCount(); i++) {
	
	                    // Get the column name of each column
	                    String columnName = resultSetMetaData.getColumnName(i+1);
	
	                    // Get the data for each column
	                    String columnData = resultSet.getString(i+1);
	
	                    // Set the Bean properties
	                    Field field = clazz.getDeclaredField(columnName);
	                    field.setAccessible(true);
	                    field.set(bean,columnData);
	                }
	
	                // Return the Bean object
	                return bean;
	            }

Copy the code

This is the strategic pattern? Is this it?? Isn’t this the use of polymorphism?

1.1 Policy Mode Description

Zen of Design Patterns:

Define a set of algorithms, encapsulate each algorithm, and make them interchangeable

The class diagram for the policy pattern looks like this:

The interface and implementation of the policy should be well understood:

  • The policy interface is equivalent to the ResultSetHandler interface we talked about above (which defines the policy’s behavior)
  • The concrete implementation is equivalent to the BeanHandler implementation we talked about above.
    • There are several other implementations, such as ListBeanHandler, MapBeanHandler, and so on

What might be confusing is that the policy pattern also has a Context Context object. What is this object for?

Zen of Design Patterns:

Context is called a Context role. It acts as a link between the preceding and the following to encapsulate policies and algorithms. It shields high-level modules from direct access to policies and algorithms and encapsulates possible changes.

There is a similar problem on Zhihu (why not call directly, instead of through Person?) :

In plain English, calling from Person is more object-oriented (shielding direct access to the concrete implementation).

First of all, we should understand a truth, that is — is it “people” travel, or train, car, bicycle, plane these means of transport travel?

Without context, the client must directly interact with the specific policy implementation, especially when it needs to provide some common functionality or store some state. Once the context is introduced, this work can be done by the context, and the client only needs to interact with the context. This makes the policy pattern more holistic and the client simpler

Specific links:

  • www.zhihu.com/question/31…

So let’s go back to the generic class diagram, and we can look at it like this:

1.2 Examples of policy patterns

Now 3y has a public account called Java3y. 3Y wants this to make more people aware of the public account Java3y. So every day I wonder how to get more fans (Hahah

So 3Y started to figure out how to do it, and 3Y discovered that there were a lot of ways to grow fans during this period. For convenience, define a general interface to facilitate management and use.

Interface:


/** * Add fan Strategy interface (Strategy) */
interface IncreaseFansStrategy {

    void action(a);
}
Copy the code

Specific measures to increase powder, for example, please shuijun:


/* ConcreteStrategy */
public class WaterArmy implements IncreaseFansStrategy {
    
    @Override
    public void action(a) {
        System.out.println("3Y awesome, I'm going to like, retweet and add chicken legs to you!"); }}Copy the code

Powder specific measures, for example, seriously write original:


/** * ConcreteStrategy */
public class OriginalArticle implements IncreaseFansStrategy{

    @Override
    public void action(a) {
        System.out.println(3Y's latest article, "Strategic Patterns, Right here?" "); }}Copy the code

3Y also came up with a lot of ways to increase their followers, such as book delivery, commercial advertising and so on… (I won’t go into details here.)

In the final analysis, no matter which kind of powder method, are carried out through 3Y.


/** * 3y(Context) */
public class Java3y {

    private IncreaseFansStrategy strategy ;

    public Java3y(IncreaseFansStrategy strategy) {
        this.strategy = strategy;
    }

    // 3y will publish the article (buy water army, send book, write zhihu drain...) .
    // Select * from 3y
    public void exec(a) { strategy.action(); }}Copy the code

So, when it comes time to tweet, 3Y can choose which way to increase its followers:

public class Main {

    public static void main(String[] args) {

        // Today is December 24, 2018
        Java3y java3y = new Java3y(new WaterArmy());
        java3y.exec();

        // Tomorrow December 25th, 2018
        Java3y java4y = new Java3y(new OriginalArticle());
        java4y.exec();
        
        / /...}}Copy the code

Execution Result:

1.3 Advantages and disadvantages of the policy mode

Advantages:

  • Algorithms can be switched freely
    • A change of strategy is convenient
  • Good scalability
    • If you add one policy, you add one more class.

Disadvantages:

  • The number of policy classes increases
    • Each policy is a class, with a low likelihood of reuse and an increasing number of classes
  • All policy classes need to be exposed
    • The upper module must know which policies are available before it can decide which to use

1.4JDK policy mode application

ThreadPoolExecutor: Are you sure you don’t want to learn about thread pools?

To learn about ThreadPoolExecutor, you must know the meaning of each argument to its constructor:


    /** * Handler called when saturated or shutdown in execute. */
    private volatile RejectedExecutionHandler handler;

	public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        //....
        this.handler = handler;
    }

    /** * Invokes the rejected execution handler for the given command. * Package-protected for use by ScheduledThreadPoolExecutor. */
    final void reject(Runnable command) {
        handler.rejectedExecution(command, this);
    }

Copy the code

RejectedExecutionHandler, which represents the rejection policy (there are four implementations: throw the exception directly, use the caller’s thread to process it, throw the task directly, and throw the oldest task)

In fact, this is the embodiment of the strategic pattern.

The last

Does the strategy mode feel so easy after watching it? Wrap it up with an algorithm interface, multiple algorithm implementations, and a Context, and you’re done.

Recommended reading and references:

  • www.cnblogs.com/lewis0077/p…
  • Zen of Design Patterns

Happy to share and export dry Java technology public account: Java3y.

Article table of Contents navigation:

  • Github.com/ZhongFuChen…