I haven’t updated it for a long time. Today I will update an article on design patterns – adapter patterns. If you’ve ever done Android development, you’re probably familiar with the term adaptation. The purpose of adaptation is to make our application suitable for all major Android phone platforms.

Adaptation, popularly speaking, is to be very individual person, to be appropriate guidance, let it play its biggest role. The person with the personality is the Adaptee, the Target is the function, and the person who guides is the Adapter.

Let’s take a simple example. I’m sure you’ve all heard this before. So, the boss of 12306 said, we are developing an online ticketing system. The boss issued orders to the manager, the manager outsourced the project to the teachers of the university to do, the teacher said, students give you a graduation topic, limit when to complete. (Of course, this is just a joke, but it’s definitely not true, 12306 is really good, in order to arouse everyone’s interest in learning, let’s play to the public).

We simplify the layers in the middle, leaving three main roles, one as boss, one as manager, and one as student. The boss puts forward the demand Target, the boss does not understand the technology, so the actual work is the student Adaptee.

Why do you need a manager, you may ask?

Why doesn’t the boss talk to the students directly? No, of course, is not because the face problems, but the boss still have more important things to do, do the overall scheduling and major policy decisions, this project is just one of the decision, so it is not convenient don’t have time to communicate with students directly, so the manager Adapter is present, is responsible for reporting to the superior, and communicate with students.

So how do you describe it in a diagram?





Class adapter structure diagram

As you can see from the figure, we are actually calling Student’s codingBuild() method in Manager. So how do you do that in pseudocode?

class Manager implements Boss extends Student{

    @Overridepublic void buildWebSystem(){ codingBuild(); }}Copy the code

That’s the simple way to write a class adaptor, so what’s wrong with writing it this way?

  1. Our default Target is Interface. What if the Target class is abstract? We know that Java does not support multiple inheritance, so this must be problematic.

  2. If Adaptee is final, it cannot be inherited.

  3. We know to use less inheritance and more composition.

So is there another way to write it? So the object adapter came along.

class Manager implements Boss{

    privateStudent stu./ /

    public void setStudent(Student stu){

        this.stu = stu;
    }

    @Override
    public void buildWebSystem(a){ tu.codingBuild(); }}Copy the code

We can see that the Adapter class holds an Adaptee object whose methods are called in the methods of the Adapter.

So what’s the advantage of writing this?

  1. We don’t care how the specific system is implemented, so we are transparent to Adapter and delegate tasks to Adaptee, as long as we know that our task requirements are met, and we don’t have to change the existing organizational structure.

  2. If we are not satisfied with what this adapter is doing, we can always replace another adapter without changing too much code.

What about the use scenarios for the adaptor pattern?

  1. This pattern can be used when you do not want to know or cannot know the specific business implementation. Since the caller is transparent, I just need to make the specification and “outsource” the implementation to the Adaptee;
  2. This pattern can be used when requirements change frequently and specific implementation flexibility needs to be improved. Technically, it’s easier to change algorithms;
  3. If you want to make an Adaptee more reusable, you can use this pattern.

The adapter pattern is basically done, isn’t it easy?

Expanding a bit, talk about two-way adapters. The bidirectional Adapter holds both Target and Adaptee. Simple example code.

class Manager implements Boss extends Student{

    private Boss boss; // Target

    private Student stu; //Adaptee

    public setBoss(Boss boss){
        this.boss = boss;
    }

    public setStudent(Student stu){
        this.stu = stu;
    }

    @Override
    public void buildWebSystem(a){

        tu.codingBuild();
    }

    public void codingBuild(a){ boss.buildWebSystem(); }}Copy the code

I don’t see much of this realization as an understanding.

There is one more default adapter that is worth mentioning. So let’s say we now have an interface class A that has A bunch of methods in it.

interface A{

    public void methodA();
    public void methodB();
    public void methodC(); . }Copy the code

MethodA (); methodA(); methodA(); B: That’s easy. Can’t you just let B implement interface A? Of course. But we must implement methodA(), methodC() for methodB()… If there are A lot of methods in A, then there will be A lot of useless code in our B class because all but methodA() are empty implementations. Is there a better way to implement it?

// Adaptor interface
public interface A {

    public void methodA(a);
    public void methodB(a);
    public void methodC(a);
    public void methodD(a);
}

// The default adapter class
public abstract class B implements A {

    @Override
    public void methodA(a) {}@Override
    public void methodB(a) {}@Override
    public void methodC(a) {}@Override
    public void methodD(a) {}}// Concrete business class
public class C extends B {

    @Override
    public void methodA(a) {
        //TODO}}Copy the code

As you can see from the code, we have introduced an abstract class B in the middle, which is used for empty implementation of all methods in interface A. Finally, the target method we want to achieve is specified in C.

What are the benefits of this?

Useless code does appear, but we only need to make it appear once, rather than implement it empty in every new class.

So why is B abstract?

The way I understand it, since all methods in B are empty implementations, this class has no real meaning. What really matters is the concrete implementation class C, which implements what we want. To avoid people instantiating this useless class, we declare it abstract. Each class has its own responsibility and name, A (adapter interface), B (default adapter class), and C(concrete business class).

Ok, adapter pattern basically said, hope to give a little help to the novice.