Eight: adapter mode

Divided into two types, classes and object adapter from the adapter implementation, both the difference is that different ways to achieve a succession using a combination of (inherited interfaces and implementations embodiment) employed.

From the use purposes, can be divided into two types, and a default adapter special adapter, except that these two different objects on a to reuse existing code and adapted to current interfaces A to provide a default implementation, the method should not be implemented to avoid the need to achieve sub-class.

 

First, it should be understood that the adapter mode is the remedy, so in the system design process please forget this design model, the model only remedy when you are helpless.

So when do we use this model? Scenario is often the case, the system has a complete class structure, and which we need to use a certain type of function (popular point that can be said method), but our clients recognize only another and are structurally unrelated to the class interface adapter mode this time is play time, we can adapt this existing class interfaces with our goals and, ultimately, a meet the required interfaces and contains functional classes to be reusable classes.

 Next, we give an example, a problem such as we mentioned in chapter observer, that is a drawback of the observer pattern, that is, if an existing class does not implement the Observer interface, so we can not class this as a observer added to the list of observers of the observer, which is really too bad.

 In this problem, we need to get an Observer class interface, but want to use the original function of the class, but we can not change the original code for this class, or the class has had a full class system, we do not want to destroy it, then your adapter model is the best choice.

 We give a concrete example, such as we hope that this will HashMap class is added to the list observer, when a difference observer, suppose we want to clear the entire MAP. But now add not go ah, why?

 Because the list of observers Observable Observer only recognize this interface, it does not recognize HashMap, how to do it?

In this case, we can use our adapter class HashMap do hands and feet, have already said, using an adapter class inherits the way we write the following adapters.

Copy the code
HashMapObserverAdapter class public <K, V> the extends the HashMap <K, V> the implements the Observer { 

    public void Update (O Observable, Object Arg) { 
        // If the observer is a change, empty the Map 
        super.clear (); 
    } 

}
Copy the code

                 That is our inheritance we want to reuse the function of the class, and we want to implement the interface adapter, where is the Observer, it will produce an adapter, the adapter has the original class (ie HashMap) function, but also has observer Interface, so the adapter can now be added to the list of observers.

                 Look, adapter class is very simple, right? So let's take a look at the object adapter, just said object adapter is the combination of the use of implementation.

                 Why use a combination of it? The above approach is not very good?

                 In essence, the reason is because JAVA single inheritance, a JAVA class can have only one parent class, so when we want to adapt the objects are two classes of time, how do you do it? Do you want to write the whole two classes extends behind you, if you do, then the compiler will express its discontent.

                 We take the example of the Observer pattern for the chapter (observer pattern more miserable old to wipe adapter mode), such as we now have a written class, assuming that it is a class entity. as follows.

Copy the code
public class User extends BaseEntity{
    private Integer id;
    private String name;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
Copy the code

                 See, most of our entity class inherits from the BaseEntity, now how do you do it, you want to have the observer function also inherit Observable class, you say how you inherit it.

                 You are not going to talk, then I do not inherit the User BaseEntity not get away, I put all the things inside BaseEntity move to the User class, or I do not inherit Observable, and all the things inside the Observable moved inside the User class.

                 This is not no, but this is a big risk, such as time to our project to scan for a subclass of BaseEntity, to do something this time if the User did not inherit BaseEntity, then you will miss out on this class, it will destroy your inheritance system, paid too much.

                 Conversely, if you do not inherit Observable, then your User class looks very messy, and I suppose now only User class can be observed, my Person class, Employee Do you want to be able to code Observable observed, COPY three times to three classes there?

                Do not forget just said, the Adapter pattern is to help us to reuse code, use the adapter mode here can help us to reuse the code or function of Observable.

                LZ based discussion above, we make the following adapters, where the use of object adapter.

Copy the code
//我们继承User,组合Observable.
public class ObservableUser extends User{
    
    private Observable observable = new Observable();

    public synchronized void addObserver(Observer o) {
        observable.addObserver(o);
    }

    public synchronized void deleteObserver(Observer o) {
        observable.deleteObserver(o);
    }

    public void notifyObservers() {
        observable.notifyObservers();
    }

    public void notifyObservers(Object arg) {
        observable.notifyObservers(arg);
    }

    public synchronized void deleteObservers() {
        observable.deleteObservers();
    }

    protected synchronized void setChanged() {
        observable.setChanged();
    }

    protected synchronized void clearChanged() {
        observable.clearChanged();
    }

    public synchronized boolean hasChanged() {
        return observable.hasChanged();
    }

    public synchronized int countObservers() {
        return observable.countObservers();
    }
    
    
}
Copy the code

              We inherit User, rather than inherit Observable, for this reason I have said, we can not destroy the inheritance hierarchy in the project, so the User (ObservableUser) now observable still in the inheritance hierarchy of our entity, if you want another has ObservableUser User property, you need to User's property to protected.

              This is just great, User we have the observable. But LZ said long ago, to utilize design patterns, this is clearly not the best solution. Because if we still Person, Employee class must have a function observable, then it is actually quite miserable, because following those Observable way we still have to copy it again.

              Tip here, I wonder if you think of a better solution yet? Especially beginners can ponder the next.

              Here are the final LZ relatively good solution that we observed is defined as the base class.

Copy the code
//我们扩展BaseEntity,适配出来一个可观察的实体基类
public class BaseObservableEntity extends BaseEntity{

    private Observable observable = new Observable();

    public synchronized void addObserver(Observer o) {
        observable.addObserver(o);
    }

    public synchronized void deleteObserver(Observer o) {
        observable.deleteObserver(o);
    }

    public void notifyObservers() {
        observable.notifyObservers();
    }

    public void notifyObservers(Object arg) {
        observable.notifyObservers(arg);
    }

    public synchronized void deleteObservers() {
        observable.deleteObservers();
    }

    protected synchronized void setChanged() {
        observable.setChanged();
    }

    protected synchronized void clearChanged() {
        observable.clearChanged();
    }

    public synchronized boolean hasChanged() {
        return observable.hasChanged();
    }

    public synchronized int countObservers() {
        return observable.countObservers();
    }
    
}
Copy the code

              This is just great, and now we have the User, Person, Employee if they wish to have a function that can be observed, it would change our adaptation to inherit BaseObservableEntity good enough, and because BaseObservableEntity inherited BaseEntity, so three of them still in our inheritance system entity, and because we are new BaseObservableEntity extend the base class, so it will not cause damage to the original inheritance system.

              Use the Adapter pattern is quite clear, the Adapter pattern we are more than two ways to reuse existing code and used, LZ just said, according to different purposes, the adapter mode can also be divided into two, then the above The first is, can be called a custom adapter , there is another called default adapter .

              First we have to say why you want to appear by default adapter, the adapter mode because in most cases is to remedy, the remedy now, then certainly we need to use this model to historical reasons.

              Let's look at the history of the reason the default adapter, I wonder if you still remember the first chapter of the general principles, LZ had mentioned a principle, the principle of minimal interfaces.

              Ideas expressed this principle is to say the behavior of the interface should be as less then remember LZ said at the time if you did not do it, then what would be the situation?

              The result is a subclass implement this interface, many ways the situation is likely to appear empty, because your interface design is too large, leading to the original method of interface should not appear there, the results are now do not have access to this subclass method, but because JAVA language rules, implements an interface must implement all its methods, so we subclass forced to write a bunch of empty method in that, just to compile.

              So in order to solve this problem, there have been the default adapter. For example, we have the following interface.

Copy the code
public interface Person {
    
    void speak();
    
    void listen();
    
    void work();
    
}
Copy the code

                 This is one of the interface that represents a person can speak, listen and work, assuming LZ two years ago, it is also at home unemployed, LZ did not work ah, but also personal LZ ah, so LZ to implement this interface, so LZ can only work methods to copy down empty on that, and assuming that LZ is deaf, well, three methods to be empty, but expressed LZ, LZ a person, LZ must be achieved person interface.

                 Of course, the above is just an example, but the real project which will be a similar situation, then how to do it?

                 This down, we default to the adapter, as follows.

Copy the code
public class DefaultPerson implements Person{

    public void speak() {
    }

    public void listen() {
    }

    public void work() {
    }

}
Copy the code

                 We have created a Person interface default implementation that there are some default method, of course, nothing to write here because it is empty, and which may be added to the actual operation in some of the default, such as if the method returns an integer result, so we default default adapter can return zeros.

                 This is just great, as long as LZ inherit the default adapter (DefaultPerson), then overwrite method LZ interest on the line, such as speak and listen, as for work, since the adapter to help us provide default implementations, so we do not need to wrote.

                 This situation actually find many, minimized because the interface design is only an ideal state, it is inevitable there will be some implementation class, for which certain methods are not interested at this time, if the method is too much, there are many sub-categories and sub-category most of the methods are empty, then it can be taken up in this way.

                 Of course, doing so violates the Richter substitution principle, but above approach already violated the principle of minimizing the interface, so we have to weigh the pros and cons of both in the real use, in the end what we need. So from this we can see, in principle, only as a guide, not necessarily can not meet all, so we must learn to choose.

                 In both scenarios are summarized adapter implementations used, both in order to reuse existing code class and adapted to interface to the client needs go up.

 1, a first adapter species, generally adapted for the case where the aim is to use the interface.

 2, the second object adapter, the adapter is generally for the object target is a class or need to multiplex more than one time use, here again a special reminder, the object adapter sometimes in order to fit more than one class together, so when it had to use in combination, and we use the object adapter, inheritance is not required, but to deal with the relationship between the actual class, which must be above example, directly or indirectly, is inherited from BaseEntity in order not to undermine our original inheritance system, but in some cases this is not necessary.

3, third default adapter, typically to make up for mistakes committed by the interface is too large, but note that weigh the pros and cons, weigh the good later consider whether to use the default adapter.

                 Well, this adapter mode share to this end, I hope you can gain points harvest

Guess you like

Origin www.cnblogs.com/2019lgg/p/11084335.html