[Design mode] Different design modes reflect IOC control inversion, design mode ioc

Source: Internet
Author: User

[Design mode] Different design modes reflect IOC control inversion, design mode ioc

Developers who have used Spring should have some knowledge about the IOC control inversion function. At first, they should know how to use dependency injection to implement IOC functions, this article describes several design patterns that use IOC's Inversion of control.

Dependency injection for IOC

Injection dependency is the most basic implementation method of IOC and one of the most common object-oriented design methods. The following example shows how injection dependency achieves control inversion:

public interface UserQueue {    void add(User user);    void remove(User user);    User get();}public abstract class AbstractUserQueue implements UserQueue {    protected LinkedList<User> queue = new LinkedList<>();    @Override    public void add(User user) {        queue.addFirst(user);    }    @Override    public void remove(User user) {        queue.remove(user);    }    @Override    public abstract User get();}public class UserFifoQueue extends AbstractUserQueue {    public User get() {        return queue.getLast();    }}public class UserLifoQueue extends AbstractUserQueue {    public User get() {        return queue.getFirst();    }}

UserQueueThe interface defines a public method for storing User objects in a queue.AbstractUserQueue provides some common methods for subsequent inheritance classes. Last user‑oqueueAndUserLifoQueue implements FIFO and LIFO queues respectively.

This is an effective way to implement subclass polymorphism.

By creating a client class that relies on the UserQueue abstract type (also known as the service in DI terminology), you can inject different implementations at runtime without restructuring the code using the client class:

public class UserProcessor {    private UserQueue userQueue;    public UserProcessor(UserQueue userQueue) {        this.userQueue = userQueue;    }    public void process() {        // process queued users here    }}

UserProcessor demonstrates that dependency injection is indeed a method of IOC.

We can use some hard encoding methods such as the new operation to directly instantiate the constructor and obtain the queue dependency in UserProcessor. However, this is a typical hard code programming. It introduces strong coupling between client classes and their dependencies, and greatly reduces testability.

This class declares the abstract class in the constructorUserQueue. That is to say, dependencies no longer use the new operation in the constructor. On the contrary, either the dependency injection framework or the factory or builders mode are used through external injection.

When dependency injection is used, the dependency control of client classes is no longer located in these classes; instead, it is implemented in the injector. See the following code:

public static void main(String[] args) {     UserFifoQueue fifoQueue = new UserFifoQueue();     fifoQueue.add(new User("user1"));     fifoQueue.add(new User("user2"));     fifoQueue.add(new User("user3"));     UserProcessor userProcessor = new UserProcessor(fifoQueue);     userProcessor.process();}

The above method achieves the expected results, andUserLifoQueue injection is also simple and clear.

 

Implement IOC in observer Mode

It is also a common and intuitive way to implement IOC directly through the observer mode. Broadly speaking, IOC is implemented by the observer. The observer mode is usually used to track the changes of the state of the model object in the context of the Model View.

In a typical implementation, one or more observers are bound to an observed object (also known as a topic in schema terminology), for example, by calling the addObserver Method for binding. Once the binding between the observer and the observer is defined, the change of the observer State will trigger the operation of the observer. Take the following example:

public interface SubjectObserver {    void update();}

When the value changes, it will trigger the simple observer called above. In actual situations, APIs with more functions are usually provided, such as the instance to be saved or the new and old values. However, you do not need to observe the action mode, the example here is as simple as possible.

Next, an observer class is given:

public class User {    private String name;    private List<SubjectObserver> observers = new ArrayList<>();    public User(String name) {        this.name = name;    }    public void setName(String name) {        this.name = name;        notifyObservers();    }    public String getName() {        return name;    }    public void addObserver(SubjectObserver observer) {        observers.add(observer);    }    public void deleteObserver(SubjectObserver observer) {        observers.remove(observer);    }    private void notifyObservers(){        observers.stream().forEach(observer -> observer.update());    }}

In the User class, when the setter method is used to change its status, the call bound to its observer will be triggered.

The following example shows how to observe the topic observer and topic:

public static void main(String[] args) {    User user = new User("John");    user.addObserver(() -> System.out.println(            "Observable subject " + user + " has changed its state."));    user.setName("Jack");}

Whenever the User object status is modified using the setter method, the observer will be notified and print a message to the console. So far, we have provided a simple use case for the observer mode. However, through this seemingly simple use case, we know how control is reversed in this case.

In the observer mode, the topic acts as the "framework layer", and it completely determines when and where to trigger calls. The observer's initiative is put out because the observer cannot determine when to call (as long as they have been registered to a topic ). This means that, in fact, we can find that the "event location" of the control is reversed-when the observer is bound to the topic:

user.addObserver(() -> System.out.println(            "Observable subject " + user + " has changed its state."));

The preceding example briefly illustrates why the observer mode is a very simple way to implement IoC. In this form of distributed design software components, controls are reversed.

 

Template Method implementation IOC

The idea of implementing the template method mode is to define a general algorithm through several abstract methods in a base class, and then let the subclass provide specific implementation, so as to ensure the algorithm structure remains unchanged.

We can use this idea to define a general algorithm to process domain entities. For example:

public abstract class EntityProcessor {    public final void processEntity() {        getEntityData();        createEntity();        validateEntity();        persistEntity();    }    protected abstract void getEntityData();    protected abstract void createEntity();    protected abstract void validateEntity();    protected abstract void persistEntity();}

processEntity()A method is a template method that defines algorithms for processing objects. Abstract METHODS represent the steps of algorithms, which must be implemented in subclasses. Multiple inheritanceEntityProcessor implements different abstract methods to implement several algorithm versions.

Although this makes clear the motives behind the template method pattern, people may wonder why this is the IOC pattern.

In typical inheritance, subclass calls the methods defined in the base class. In this mode, the method implemented by the subclass (algorithm step) is called by the template method of the base class. Therefore, the control is actually performed in the base class, rather than in the subclass.

 

Summary:

Dependency injection: the control for obtaining dependency from the client no longer exists in these classes. It is stored by the underlying injector/DI framework.

Observer mode: When the subject changes, control is transferred from the observer to the subject.

Template Method mode: control occurs in the base class that defines the template method, rather than the subclass that implements the algorithm step.

 

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.