preface

I once had a resolution to memorize all 23 design patterns, but I kept memorizing and forgetting, forgetting and continuing to memorize. Although there is a lot of teaching on the Internet, analysis, write yourself, than watching ten times more profound. Pick up a few words. Then again, we code according to design patterns all the time.

Seven principles of design patterns

Describe it in the simplest possible terms

1. Open Closed Principle

Extensions to classes are open and closed for modification. When a program needs to extend a class, do not modify the original code, but extend the class by inheritance. Objective: To reduce maintenance risks

2. Single Responsiblity Principle

Each class should have only one responsibility. Purpose: To improve readability

3. Liskov Substitution Principle

When a subclass inherits from a parent class, it can implement the abstract methods of the parent class. Instead of overwriting the methods of the parent class, the subclass adds its own special methods. Purpose: To prevent inheritance problems

4. Dependency Inversion Principle

Programs should rely on abstract interfaces, not on concrete implementations, programming for interfaces. Purpose: To facilitate code upgrade

5. Interface Segregation Principle

Large interfaces are broken down into smaller and more specific interfaces, one for one business logic. Objective: Function decoupling, high cohesion, low coupling

6. Principle of Least Knowledge

One object should know as little as possible about other objects. Purpose: Do your own thing

Composite Reuse Principle

Use object composition rather than inheritance for reuse purposes. Inheritance breaks encapsulation, and any change in the parent class can cause problems in the subclass. Priority is given to synthetic reuse, the combined use of classes A and B, rather than the use of B inheriting FROM A. Purpose: Reduce coupling with less inheritance

23 design patterns

The 23 design patterns fall into three categories: creative, structural, and behavioral. As the name suggests, creative is how objects are created. Structural is the relationship of objects to objects, into a larger structure. Behavior is the control of complex processes at run time.

Create a type

1. Singleton Pattern

Purpose: mainly a class, frequently created, destroyed advantages: only one instance in memory, reduce overhead disadvantages: no interface, cannot inherit, violates the single responsibility principle implementation: 1. Lazy static method, when used to create object 2. Hanhan-style static variable, directly new object 3. Double lock two if statements, the first if to prevent unnecessary thread synchronization, the second if to prevent the second thread from creating objects repeatedly, volatile to prevent instruction reordering. The principle is similar to lazy creating 5 in the static block. Enumeration, enumeration compiled, also in the static block new object

Public class Singleton{private volatile static Singleton instance; private Singleton(){}; public static Singleton getInstance(){ if(instance==null){ sychronized(Singleton.class){ if(instance==null) instance=new  Singleton(); } } return instatnce; }}Copy the code

There is a hidden abstract class in Android

public abstract class Singleton<T> { public Singleton() { } private T mInstance; protected abstract T create(); public final T get() { synchronized (this) { if (mInstance == null) { mInstance = create(); } return mInstance; } } } private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton = new Singleton<IActivityTaskManager>() { @Override protected IActivityTaskManager create() { final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE); return IActivityTaskManager.Stub.asInterface(b); }};Copy the code

This is used to retrieve AMS objects. If not, the ServiceManager retrieves them. This Singleton is a hidden class, so you can copy it directly.

2. Factory Pattern

Purpose: To solve the problem of interface selection Advantages: If you want to create an object, as long as you know the name of the line, shielding the internal implementation, as long as you care about the shortcomings of the interface: When you add a product, you need to add an implementation class and a Factory, such as Dagger2. Add an injected Bean, and Dagger2 will generate a Factory class for you. Space increases to achieve:

public interface Clothes { void getClothes(); } public class implements Clothes {@override public void getClothes() {system.out.println (" Jacket "); }} public implements Clothes {@override public void getClothes() {system.out.println (); Public class WardrobeFactory {public Clothes getShape(String shape) {switch (shape) {case "Jacket": return new Jacket(); case "Sweater": return new Sweater(); } return null; }}Copy the code

Wardrobe is a factory, wardrobe has clothes, abstract clothes, clothes can be a jacket or a sweater in Android according to the name of the object, such as access to system services

context.getSystemService(Service.ALARM_SERVICE)
String ALARM_SERVICE = "alarm"     
Copy the code

Obtain the alarm service

3. Abstract Factory Pattern

Purpose: To solve the problem of interface selection Advantage: When there are many types of products, the object of the current product category is obtained according to the name disadvantage: It is very difficult to expand, add a new product of the same kind, need to add a new factory implementation:

Public Trousers {void getTrousers(); } public class Jeans implements Trousers {@override public void getTrousers() {system.out.println (" Jeans "); }} // Trousers {@override public void getTrousers() {system.out.println (" Shorts "); }} public interface {void getClothes(); {@override public void getClothes() {system.out.println (" Sweater "); }} public class implements Clothes {@override public void getClothes() {system.out.println (" implements Clothes "); }} // There are clothes and pants, abstract factory // Abstract factory, Public abstract class AbsFactory {public abstract Trousers getTrousers(String Trousers); public abstract Clothes getClothes(String clothes); } public class ClothesFactory extends AbsFactory{@override public Trousers getTrousers(String Trousers) {return  null; } @Override public Clothes getClothes(String clothes) { switch (clothes){ case "Jacket": return new Jacket(); case "Sweater": return new Sweater(); } return null; }} public class TrousersFactory extends AbsFactory {@override public Trousers getTrousers(String Trousers) { switch (trousers){ case "Shorts": return new Shorts(); case "Jeans": return new Jeans(); } return null; } @Override public Clothes getClothes(String shape) { return null; Public class WardrobeFactory {public static AbsFactory getFactory(String choice){switch (choice){case "Clothes": return new ClothesFactory(); case "Trousers": return new TrousersFactory(); } return null; }} / / use / / to take pants AbsFactory AbsFactory = WardrobeFactory. GetFactory (" Trousers "); // Trousers shorts = absfactory.gettrousers (" shorts "); // Shorts shorts. GetTrousers ();Copy the code

More code, or more clear, the factory abstract. Abstract Engineering focuses on the relationships between products. In Android, there are fewer abstract factories. You can think of the entire Service as a large abstract factory, retrieving the Service by name, retrieving the Service object, and calling the abstract methods in the object.

4. Prototype Pattern

Objective: Fast and efficient object creation Advantages: improved performance, no constructor limitations Disadvantages: with cloning method, need to consider the deep copy and shallow copy problem implementation:

public class Sheep implements Cloneable { String name; public Sheep(String name){ this.name = name; } public Object clone(){ Object obj = null; try { obj = super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return obj; }}Copy the code

To complete the Cloneable method, add a clone method. Object also has a clone method, which calls the Native method to clone an Object at the bottom. In the android

public class Intent implements Parcelable, Cloneable {
    @Override
    public Object clone() {
      return new Intent(this);
    }
}
//okhttp中 也用到了
@Override public RealCall clone() {
  return RealCall.newRealCall(client, originalRequest, forWebSocket);
}
Copy the code

All it really means is copying a new object.

5. Builder Pattern

Purpose: Configure a complex object Advantage: Independent, easy to extend Disadvantage: If the object is complex, there are many builder class implementations:

public class Dialog { String title; boolean mCancelable = false; Dialog(String title,boolean mCanclable){ this.title = title; this.mCancelable = mCanclable; } public void show() { System.out.print("show"); } static class Builder{ String title; boolean mCancelable = false; public Builder setCancelable(boolean flag) { mCancelable = flag; return this; } public Builder setTitle(String title) { this.title = title; return this; } public Dialog build(){ return new Dialog(this.title,this.mCancelable); }}}Copy the code

The builder is not formal; the builder pattern is used to create a complex object. On Android, Dialog uses builder mode, third-party libraries okHTTP, Retrofit

structured

6. Proxy Pattern

Purpose: To enhance its responsibilities, such as access to remote servers, if direct access may bring some trouble, through a proxy to help us access advantages: clear responsibilities, easy to expand disadvantages: adding proxies may lead to slow, proxy classes will be complicated to implement:

Public interface DataBase {void select(); Public class RealImage implements DataBase {@override public void select() {system.out.println (" query "); Public class ProxyDB implements DataBase{RealImage RealImage; public ProxyDB(){ if(realImage==null){ realImage = new RealImage(); } } @Override public void select() { realImage.select(); } // use DataBase proxyDb = new proxyDb (); proxyDb.select();Copy the code

The proxy class ProxyDB is used to access data, not directly to the database. In Android, when we write an AIDL file, the compiler automatically adds some code to it

public interface IRemoteService extends android.os.IInterface{ public static abstract class Stub extends android.os.Binder implements ... { public static com.learnaidl.IRemoteService asInterface(..) { return new .. Proxy(obj); } private static class Proxy implements com.learnaidl.IRemoteService{ ... }} // Use iremoteservice.stub ()Copy the code

Get the object from the IRemoteService Stub class, which is created from a proxy class. To put it another way, the proxy pattern implements an interface and implements a method that can do anything.

7. Facade Pattern

Objective: Reduce the system complexity Advantages: improve flexibility, security disadvantages: violate the open and close principle, Demeter principle, change things relatively troublesome implementation:

Public interface Action {void open(); Public class Lamp implements Action {@override public void open() {system.out.println (" Lamp "); Public class TV implements Action {@override public void open() {system.out.println (" implements TV "); Public class RemoteControl {Action lamp; Action tv; public RemoteControl(){ lamp = new Lamp(); tv = new TV(); } public void openLamp(){ lamp.open(); } public void openTv(){ tv.open(); }}Copy the code

The remote control can turn on both lights and TV. This “remote control” is not a single responsibility. It is not limited to interfaces. If functionality is aggregated into a class, it can still be called a facade pattern. Think of it as a receptionist. In Android, the Context is in appearance mode, you can open an Activity, you can open a Service, you can broadcast, and so on.

Decorator Pattern ()

Purpose: to solve the expansion of the subclass expansion problem, such as the spread of pancakes, you can spread pancakes before, fried an egg, spread pancakes, spread sauce advantages: flexible expansion disadvantages: too much decoration, will be very complex to achieve

Public interface Pancake {void Pancake (); } public class BeefPancake implements Pancake{@override public void Pancake () {system.out.println (" BeefPancake "); }} public class Worker {Pancake; public Worker(){ pancake = new BeefPancake(); } public void makePancake(){system.out.println ();} public void makePancake(){system.out.println (); pancake.pancake(); System. The out. Println (" sprinkle sauce "); }} // use Worker Worker = new Worker(); worker.makePancake();Copy the code

To put it bluntly, decorating patterns, decorating things, actually function before and after decorating some other content. In Android, Context, ContextImpl is just a decorator mode, and we definitely do something before and after startActivity().

9. Flyweight Pattern

Disadvantages: Improves the complexity of the system. If some objects are fixed, it will cause confusion when they are changed.

Public class HttpFactory {public static final HashMap<String,Request>  requestMap = new HashMap<>(); public Request getRequestList(String name) { Request request = (Request) requestMap.get(name); if(request==null){ request = new Request(); requestMap.put(name,request); } return request; }} // Use HttpFactory factory = new HttpFactory(); Request request1 = factory.getRequestList("baidu"); Request request2 = factory. GetRequestList ("baidu");Copy the code

It’s kind of a cache, you put objects in there, you take them from there when you need them, and if you need the same thing, you return the objects that you already have. On Android, obtaining Message can be obtained using message.obtain (). Many strings are cached in the JVM. We can say that we use the share model all the time.

10. Composite Pattern

Purpose: Used to describe the relationship between whole and part, for example, in a tree, a node can be root node or leaf node. Advantage: Easy to call, and nodes can be added freely. Disadvantage: In the combined mode, all rely on implementation classes instead of interfaces, which violates the dependency inversion principle.

Public class ListNode {int data; ListNode left; ListNode right; }Copy the code

The nodes of a binary tree can be either root or leaf nodes. In Android, the relationship between View and ViewGroup, ViewGroup can be a View, and can contain the View.

11. Adapter Pattern

Purpose: To solve the bridge between two incompatible interfaces, compatible conversion advantages: let two unrelated classes run together, improve reuse disadvantages: use too much, will make the system become messy implementation:

Public class Adapter {public void getView(int I){system.out.println (" getView "+ I); ListView extends Adapter{public void show(){system.out.print (" loop View"); for(int i=0; i<3; i++){ getView(i); Public class GridView extends Adapter{public void show(){... getView(i); }}Copy the code

Adapter pattern can be implemented using inheritance, there is no higher abstraction, of course, can also be abstracted out of the Adapter content, just to show that the ListView, GridView fit Adapter class. In Android, ListView, RecyclerView are used Adapter mode, ListView adaptor, ListView just ItemView, no matter how specific display, Adapter just display. Like the card reader, the card reader acts as an adapter between memory and the computer.

12. Bridge Pattern

Purpose: To separate two classes that can change independently, without inheritance, inheritance will cause the explosion of class growth advantages: abstract separation, easy to expand, details transparent disadvantages: will increase the difficulty of system design.

Public interface Color {void draw(String box); } // something public class implements Color{@override public void draw(String STH) { System.out.println("red "+ sth); }} public abstract class Box {Color Color; public Box(Color color){ this.color = color; } abstract void getBox(); } public class RedBox extends Box {public RedBox(Color Color) {super(Color); } @Override void getBox() { this.color.draw("box"); } // use RedColor RedColor = new RedColor(); Box box = new RedBox(redColor); box.getBox();Copy the code

If the class has two dimensional variations, for example, the color may have red and green, and the bag may have handbag and wallet. For these two dimensional variations, bridging is appropriate. More intuitively speaking, for example, a USB cable can be plugged into different mobile phones on the left and different power supplies on the right. In Android, the View of the entire View,View, Button, ViewGroup and so on are changes in the View dimension, all have onDraw() method to implement different views. The other dimension is to draw the View onto the screen. In my opinion, this RexBox is like a View, and RedColor is like drawing to the screen.

Behavior type

13. Template Pattern

Purpose: Fixed some methods, just follow them, such as put the elephant in the refrigerator, open the refrigerator, put in the refrigerator, close the refrigerator Advantage: Behavior is controlled by the parent class, easy maintenance Disadvantage: Resulting in more classes, larger system Implementation:

public abstract class BaseActivity {

    abstract void onCreate();
    abstract void onDestory();
}
public class HomeActivity extends BaseActivity {
    @Override
    void onCreate() {
    }

    @Override
    void onDestory() {
    }
}
Copy the code

The idea is to abstract out the common methods, override them, and control the behavior of the parent class. As an Android developer I use it every day…

14. Strategy Pattern

Purpose: To solve many if else cases Advantages: can avoid multiple judgment conditions, good scalability Disadvantages: class will increase

RecyclerView public class RecyclerView {private Layout; public void setLayout(Layout layout) { this.layout = layout; If (layout = = "sideways") {} else if (layout = = "vertical") {} else if (layout = = "checked") {} else {} enclosing layout. The doLayout (); }} public interface Layout {void doLayout(); } public class Layout implements Layout{@override public void doLayout() { System.out.println("LinearLayout"); }} public class implements Layout{@override public void doLayout() { System.out.println("GridLayout"); } } public class RecyclerView { private Layout layout; public void setLayout(Layout layout) { this.layout = layout; this.layout.doLayout(); }}Copy the code

Here is a direct example of Android RecyclerView. When we choose the layout of RecyclerView, we choose a strategy.

15. Mediator Pattern

Purpose: To solve the coupling between objects Advantages: reduced complexity, decoupling between classes disadvantages: Intermediaries can be too large to maintain implementation:

Public class ChatRoom {public static void showMessage(User User,String MSG){ System.out.println(user.name+":"+msg); }} public class User {String name; public User(String name){ this.name = name; } public void sendMessage(String msg){ ChatRoom.showMessage(this,msg); } // use User h1 = new User("h1"); User h2 = new User("h2"); h1.sendMessage("hello"); h2.sendMessage("you too~");Copy the code

The chat room acts as an intermediary, passing messages between two people. If the chat room new functions, will lead to more and more chat room code, not good maintenance. In Android, mediators are used all the time, P for MVP, C for MVC, VM for MVVM, you and ME. ?????

Observer Pattern

Objective: an object change notify other objects, ensure cooperation advantages: the coupling of the observer and the observed is abstract, that is to say, by the method of abstract, give specific class notice faults: if there are many observers, the observed hair message, can be slow, if not careful observer and the observed have rely on, will be a circular reference Implementation:

Public abstract class DoWork {protected Teacher Teacher; abstract void doHomeWork(int i); Public class Teacher {private List<Student> Students = new ArrayList<>(); private int index; public void attach(Student student){ this.students.add(student); } public void dispatchHomeWork(int index){ this.index = index; notifyAllStudent(); } public void notifyAllStudent(){ for (Student stu:students) { stu.doHomeWork(index); Public class Student extends DoWork {public class Student(Teacher){this. Teacher = Teacher; this.teacher.attach(this); } @override void doHomeWork(int I) {system.out.println (this+": doHomeWork "+ I); } // use Teacher Teacher = new Teacher(); new Student(teacher); new Student(teacher); new Student(teacher); teacher.dispatchHomeWork(1); teacher.dispatchHomeWork(3);Copy the code

This is fine, and the key code is observed through an ArrayList. In Java, the JDK already implements the good Observer pattern. Click on the source code and you’ll see that he’s saving a vector

public class Observable {
    private boolean changed = false;
    private Vector<Observer> obs;
}
Copy the code
17. State Pattern

Purpose: Objects depend on a state, and objects can change their behavior according to the state. Advantages: State transitions are combined with logic, not separated by if statements. Disadvantages: Complex structure and increased number of classes.

Public interface State {void doAction(MediaPlayer Activity); Public class implements State{@override public void doAction(MediaPlayer activity) { System. The out. Println (activity + ": the OnStart"); Public class implements State{@override public void doAction(MediaPlayer activity) { System. The out. Println (activity + ": OnStop"); }} public class MediaPlayer {State State; public void setState(State state){ this.state = state; } public State getState() { return state; }} // Use MediaPlayer activity = new MediaPlayer(); OnStart onStart = new OnStart(); onStart.doAction(activity); OnStop onStop = new OnStop(); onStop.doAction(activity);Copy the code

Two states, start and end, are defined for the player to operate on. In Android, players, for example, pause playback depending on their state. Methods such as fragments, which run their own onCreate, also depend on the Activity’s lifecycle state.

18. Chain of Responsibility Pattern

Purpose: Mainly used for decoupling, customers only need to send the message to the responsibility chain, no need to pay attention to the details of the request and delivery process advantages: decoupling, simplified operation disadvantages: performance will be slightly affected, debugging is not easy to achieve:

Public interface Interceptor {String chain(String inData); Public class CacheInterceptor implements Interceptor {@override public String chain(String inData) {return InData += "cache "; Public class CallServerInterceptor implements Interceptor{@override public String chain(String inData) { Return inData += "call server "; Public class RealInterceptor {List<Interceptor> List = new ArrayList<>(); public RealInterceptor(){ list.add(new CacheInterceptor()); list.add(new CallServerInterceptor()); } public String request(String st){ String result = ""; for (int i=0; i<list.size(); i++){ result += list.get(i).chain(st); } return result; RealInterceptor = new RealInterceptor(); String result = realinterceptor. request(" request ->"); System.out.println(result);Copy the code

Just like a chain, the chain of responsibility can be increased or decreased in the middle, like “beating a drum to pass flowers”, one by one. In Android, the event distribution mechanism, the parent View receives the event, passed to the child View. The third party library OKHTTP also uses interceptor mode for a network request.

19. Memento Pattern

Objective: under the premise of without destroying encapsulation, capture an object’s internal state, and save, can according to the state after the restore to its original appearance Advantages: provides a can restore mechanism, encapsulates the information, the user does not need too much care about the details Disadvantages: consume resources, if save the content is too big, too much will take up a lot of resources to achieve:

Public class Layer {private String state; public Layer(String state) { this.state = state; } public String getState() { return state; } public void setState(String state) { this.state = state; }} public class Manager {private Layer mLayer; public Layer save(String state){ return new Layer(state); } public void restore(Layer layer){ mLayer = layer; } public Layer getmLayer() { return mLayer; Public class PhotoShop {private List<Layer> layerList = new ArrayList<>(); public void ctrl_S(Layer mLayer){ layerList.add(mLayer); } public Layer ctrl_Z(int index){ return layerList.get(index); } // use PhotoShop PhotoShop = new PhotoShop(); Manager manager = new Manager(); Ctrl_S (manager.save(" first layer ")); Ctrl_S (manager.save(" layer 2 ")); manager.restore(ps.ctrl_Z(1)); System.out.println(" current is: "+ manager.getMLayer ().getState()); Ctrl_S (manager.save(" third layer ")); Ctrl_S (manager.save(" layer 4 ")); manager.restore(ps.ctrl_Z(3)); System.out.println(" current is: "+ manager.getMLayer ().getState());Copy the code

Just like in Photoshop,Ctrl+S saves one layer and Ctrl+Z reverses one. In Android, the Activity’s onSaveInstanceState saves the data and restores the data in onCreate, just like playing an archive game

20. Iterator Pattern

Purpose: Traversal an object Advantage: Access an aggregated data, which does not expose the internal content Disadvantages: Increases the number of classes, increasing system complexity

Public interface Iterator {Boolean hasNext(); Object next(); } public interface Container{Iterator getIterator(); } // implements Container {public String[] names = {"name1"," name2","name3", "name4"}; @Override public Iterator getIterator() { return new NameIterator(); } class NameIterator implements Iterator{ int index; @Override public boolean hasNext() { if(index < names.length){ return true; } return false; } @Override public Object next() { if(this.hasNext()){ return names[index++]; } return null; }} // use NameContainer = new NameContainer(); Iterator it = nameContainer.getIterator(); while(it.hasNext()){ String name = (String) it.next(); System.out.println(name); }Copy the code

Iterator interface, which must implement the next object and whether there is a next object. The Container interface needs to return a class that implements Iterator. In Java, the inner class KeySet of HashMap has Iterator, and in Android, the inner class Cursor of HashMap has Cursor

21. Interpreter Pattern

Purpose: For some fixed method structures such as XML, build a class to explain it advantages: good scalability, flexible, add new expression disadvantages: few usage scenarios, difficult to maintain, usually use recursive implementation:

SelectInterpreter = new SelectInterpreter(); SelectInterpreter. Interpreter (" check t_name "); Public interface Interpreter {String Interpreter (String SQL); } // Query Interpreter public class SelectInterpreter implements Interpreter {@override public String Interpreter (String SQL) {// Select * from t_user; // select t_user if(SQL. IndexOf (" ")==0){int start = SQL. IndexOf (" ")+1; int end = sql.length(); String tableName = sql.substring(start,end); System.out.println(" query table: "+tableName); }else{ System.out.println("sql error"); } return null; }}Copy the code

SQL is a description language. Typically, SQL queries to a table require select * from T_user, which is a database-defined syntax. Now I’ll explain, if I want to query my database, I’ll just look t_name. It’s a little crazy, but it should make sense. In android, what you do is you define the XML layout, and then you setContentView(XML), and you put the XML in, and in this case you use the interpreter schema, and you use XmlResourceParser or something like that to interpret the XML as an object.

22. Command Pattern

Purpose: Also used for decoupling. In general, requester and implementer are coupled, but in some situations, recording, revoking, and redoing behaviors are not suitable for each other. Advantages: Decoupling, easy to expand Disadvantages: command classes can change many implementations:

Public interface Order {void execute(); } public class BuyStock implements Order{Stock Stock; public BuyStock(Stock stock){ this.stock = stock; } @Override public void execute() { this.stock.buy(); Public class Stock implements Order {Stock Stock; public SellStock(Stock stock){ this.stock = stock; } @Override public void execute() { this.stock.sell(); Public class Stock {public void buy(){system.out.println ("buy"); } public void sell(){ System.out.println("sell"); Public class Manager {private List<Order> List = new ArrayList<>(); public void takeOrder(Order order){ this.list.add(order); } public void placeOrder(){ for (Order order:list) { order.execute(); } list.clear(); }} // use // Manager Manager = new Manager(); // Stock Stock = new Stock(); Order order1 = new BuyStock(stock); Order order2 = new SellStock(stock); manager.takeOrder(order1); manager.placeOrder(); manager.takeOrder(order2); manager.placeOrder();Copy the code

There are four classes, one for buying stocks, one for selling stocks, one for managers, and one for stocks. Buy and sell are equivalent to an order, and other orders can be added. In short, define an order to buy stocks, give the order to the manager, and the manager carries it out. On Android, the PackageManagerService uses the command mode to parse and manage the APK. The command pattern is relatively broad, encapsulating a request as an object and recording or revoking the request. For example, a Call used by a thread pool or okHTTP for a request can be treated as a command.

23. Visitor Pattern

Objective: To solve the problem of stable data structure and volatile operational coupling Advantages: Consistent with single responsibility, easy to extend disadvantages: violation of Demeter principle, dependency inversion principle, rely on concrete implementation class, not abstract implementation:

Public abstract class Action {abstract void accept(Visitor Visitor); } public class CameraSystem extends Action {@override void accept(Visitor Visitor) {Visitor. Visitor (this); Public class ImageSystem extends Action {@override void accept(Visitor Visitor) {Visitor. Visitor (this); } public int getSize(){ return 10; Public interface Visitor {void Visitor (ImageSystem ImageSystem); void visitor(CameraSystem cameraSystem); } public class implements Visitor {@override public void Visitor (ImageSystem ImageSystem) { System.out.print(" Access image "); System.out.print(" total "+ imagesystem.getSize ()); } @override public void visitor(CameraSystem) {system.out.print (" CameraSystem "); App1 = new App1(); ImageSystem imageSystem = new ImageSystem(); imageSystem.accept(app1);Copy the code

The code doesn’t look very complicated, but I’ve written a code that’s easy to understand. The visitor must be an abstract class that accesses the content of an action, and the image system and the camera system do that. App1 implements the visitor interface, which means App1 can access the picture system and camera system. Another example is cotton and paper. In a clothing factory it can be made into sweaters and labels, in a money factory it can be made into paper bills and packaging. The purpose of the visitor is: stable data structure and variable operation, coupling problem, I don’t think I need to explain.

conclusion

The 23 design patterns, divided into creation, structure and behavior, all revolve around seven design principles, although some design patterns sacrifice some principles for better results. Regardless of the design pattern, all the code, nothing more than to use, abstract class, interface, implementation class, plus the combination of interface and implementation class, implementation class and implementation class combination of the code written. Design patterns are a summary of our code design experience, from which we develop code that is easy to understand, reliable and reusable. Reference: www.runoob.com/design-patt…