There are six principles and twenty-three design patterns in design patterns.

The six principles are single responsibility principle, open and close principle, Richter substitution principle, dependence inversion principle, interface isolation principle, Demeter principle.

  • Twenty-three Design Mode: Singleton pattern, Builder Models, prototype pattern, factory method, abstract factory pattern, strategy pattern, state model, the chain of responsibility pattern, the interpreter, command mode, the observer pattern, memos, iterators, template method, the visitor pattern, mediation patterns, the proxy pattern, combination mode, the adapter pattern, decorative pattern, the flyweight pattern, appearance, bridge .

Now let’s introduce design principles.

SRP: Single Responsibility Principle

  • define

For a class, there should be only one cause for change. There should be only one duty.

In plain English, a class or method should do one thing.

  • For example,

For example, image loading is divided into image downloading, saving to cache, image display and so on. We should define separate methods for each of these parts; If the usage is high, it is better to define a separate class, rather than a single class method.

  • Bad code
public class ImageLoader {
    public void displayImage(ImageView imageView, String url){
        / / download
        // Display the image
        // Image cache}}Copy the code
  • To optimize the
public class ImageLoader {
    /** * download */
    public Bitmap download(String url){
        Bitmap bitmap = null;
        // Download the image
        / /...
        return bitmap;
    }
    
    public void displayImage2(ImageView imageView, String url){
        Bitmap bitmap = download(url);
        // Display the image
        / /...
        // Image cache
        imageCache(bitmap);
    }
    
    public void imageCache(Bitmap bitmap){
        // Image cache
        / /...}}Copy the code
  • SRP code
/** * Download class */
public class Download {
    /** * download **@paramUrl Download address *@returnPicture * /
    public Bitmap download(String url) {
        Bitmap bitmap = null;
        System.out.println("Download picture");
        returnbitmap; }}/** * Cache class */
public class Cache {
    /** * cache images *@param* / bitmap images
    public void imageCache(Bitmap bitmap){
        System.out.println("Cache images"); }}/** * image loading class */
public class ImageLoader {
    /** * 3@paramImageView image control *@paramUrl Image address */
    public void displayImage3(ImageView imageView, String url){
        Download download = new Download();
        Bitmap bitmap = download.download(url);
        // Display the image
        System.out.println("Show picture");
        / /...
        // Image cache
        Cache cache = newCache(); cache.imageCache(bitmap); }}Copy the code

OCP: Open Close Principle

  • define

Objects (classes, modules, functions, etc.) in software should be open to extension, but closed to modification.

It is the most fundamental design principle guiding us to build stable and flexible systems.

  • For example,

In fact, there are many OCP examples in development, such as: Adapter for List in Android (Adapter pattern, also following OCP), Listener, etc.

  • Bad code
public class DrawShape {
    // TODO bad code
    public void drawView(int type){
        if (1== type){
            System.out.println("Circular");
        }else if (2==type){
            System.out.println("Rectangle"); }}}public class Draw {
    public static void main(String[] args) {
        DrawShape drawShape = new DrawShape();
        // TODO bad code
        // Draw a circle
        drawShape.drawView(1);
        // Draw a rectangle
        drawShape.drawView(2); }}Copy the code
  • OCP code
/** * base class */
public abstract class BaseShape {
    / / drawing
    public abstract void drawView(a);
}

/** * circle */
public class Circle extends BaseShape {
    public void drawView(a) {
        System.out.println("Circular"); }}/** ** rectangle */
public class Rectangle extends BaseShape {
    public void drawView(a) {
        System.out.println("Rectangle"); }}/**
 * 绘制
 */
public class DrawShape {
    public void drawView(BaseShape draw){
        / /... Other processingdraw.drawView(); }}public class Draw {
    public static void main(String[] args) {
        DrawShape drawShape = new DrawShape();
        // Draw a circle
        drawShape.drawView(new Circle());
        // Draw a rectangle
        drawShape.drawView(newRectangle()); }}Copy the code

This may be a quasi-explosion, but it reduces coupling and is more efficient.

LSP: Liskov Substitution Principle

  • define

A derived (subclass) object can replace its base (superclass) object in a program.

This means that all references to the base class must be able to transparently use objects from its subclasses. A parent class can be replaced with a subclass, and a subclass cannot be replaced with a parent class. Richter’s substitution principle mainly describes some principles about inheritance, that is, when inheritance should be used, when inheritance should not be used, and the underlying principles. Richter substitution is the basis of inheritance reuse, which reflects the relationship between base class and subclass, is a supplement to the open and closed principle, and is the specification of concrete steps to achieve abstraction.

  • For example,
/** ** parent */
public class Parent {
    public void method1(a){
        System.out.println("method1"); }}/** * subclass 1 */
public class Children1 extends Parent {
    public void method2(a){
        System.out.println("method2");
    }

    @Override
    public void method1(a) {
        super.method1();
        System.out.println("Children1 method1"); }}/** * subclass 2 */
public class Children2 extends Parent {
    public void method3(a){
        System.out.println("method3");
    }
    @Override
    public void method1(a) {
        super.method1();
        System.out.println("Children2 method1"); }}public class Client {
    public void method(Parent child){ child.method1(); }}/ / call
public static void main(String[] args) {
    Client client = new Client();
    client.method(new Children1());
    client.method(new Children2());
}
Copy the code

DIP: Dependence Inversion Principle

  • define

Programs rely on abstract interfaces, not concrete implementations. Simply put, requiring that the abstraction be programmed, not the implementation, reduces the coupling between the client and the implementation module.

The REPRESENTATION of a DIP in Java is that dependencies between modules occur through abstraction, with no direct dependencies between implementation classes. Dependencies are generated through interfaces or abstract classes. It’s actually more interface oriented or abstract oriented.

  • The key point
  1. High-level modules should not depend on low-level modules; both should depend on their abstractions
  2. Abstractions should not depend on details
  3. Details should depend on abstractions
  • For example,
public interface TestListener {
    void test(a);
}
public class TestListenerImpl implements TestListener {
    public void test(a) {
        System.out.println("TEST"); }}public class Client {
    private TestListener testListener;
    public void setTestListener(TestListener testListener) {
        this.testListener = testListener;
    }

    public void method(a){
        this.testListener.test(); }}/ / execution
    public static void main(String[] args) {
        Client client = new Client();
        client.setTestListener(new TestListenerImpl());
        client.method();
    }
Copy the code

ISP Interface Segregation Principles

  • define

A client should not rely on interfaces it does not need. The dependency of one class on another should be based on the smallest interface.

An interface represents a role, and different roles should not be assigned to the same interface. Unrelated interfaces merge into one large, bloated interface, which contaminates roles and interfaces. The interface isolation principle is similar to the single responsibility principle in that a class or interface, method or interface method does only one thing.

  • For example,
  • Bad example
public interface BadListener {
    void badFood(a);
    void badThing(a);
}
Copy the code

In the example above, the bad thing, which could be food, could be an item, once this interface is implemented, there will be a callback that is not needed. Resulting in interface waste (pollution).

  • ISP example
public interface BadFoodListener {
    void food(a);
}
public interface BadThingListener {
    void thing(a);
}
Copy the code

The above interface, the use of that interface, the implementation of that interface can not cause the waste of interface methods.

LOD principle (Law of Demeter)

  • define

Also known as The Least Knowledge Principle. One object should know the least about other objects.

The less a class knows about other classes, the better. That is, an object should know as little about other objects as possible, communicate only with friends, and not talk to strangers.

  • meaning

The original intention of Demeter’s rule is to reduce coupling between classes. Because each class minimizes its dependence on the others, it is easy to make the functional modules of the system functionally independent, with no (or few) dependencies on each other.

  • For example,

For example, if a tenant wants to find a house through an intermediary, the tenant wants a price of 20 square meters and 2000 yuan a month. At this time, the intermediary has two schemes to provide tenants: the first is to give all the houses to the tenants, and the tenants choose the second is to screen out the houses according to the requirements and give them to the tenants. The first increases the coupling between the tenant and the property; The second one uses the LOD principle to reduce the coupling between the tenant and the house, so that the tenant can only see the house that meets the conditions. In layman’s terms, it puts the screening process in the hands of an agent that the tenant can contact, who deals with the property, with which the tenant has little connection.

/** ** **
public class Room {
    private int are;
    private int pay;

    public int getAre(a) {
        return are;
    }

    public void setAre(int are) {
        this.are = are;
    }

    public int getPay(a) {
        return pay;
    }

    public void setPay(int pay) {
        this.pay = pay; }}/** ** intermediate */
public class Mediator {
    private List<Room> allRooms = new ArrayList<Room>();
    public Mediator(a){
        for (int i=0; i<10; i++){ Room room =new Room();
            room.setAre((i+1) *5);
            room.setPay((i%4= =0?1:i%4) *1000); allRooms.add(room); }}public List<Room> getAllRooms(a) {
        return allRooms;
    }
    / / after transforming
    public Room rentRoom(int are, int pay){
        // Obtain all properties through an agent
        for (Room room: allRooms){
            if (isSuitable(room, are, pay)){
                returnroom; }}return null;
    }

    // Determine if there is a suitable one after modification
    private boolean isSuitable(Room room, int are, int pay){
        // Filter houses
        return true; }}/** * Tenant */
public class Tenant {

    // Bad example
// // before transformation
// public void rentRoom(Mediator mediator){
// // Acquire all houses through an agent
// List
      
        allRoom = mediator.getAllRooms();
      
// for (Room room: allRoom){
// if (isSuitable(room)){
// system.out. println(" house found ");
/ /}
/ /}
/ /}
//
// // before retrofitting - judge whether there is a suitable one
// private boolean isSuitable(Room room){
// // Screen housing
// return true;
/ /}

    // After the modification - good example
    public void rentRoom(Mediator mediator){
        System.out.println(mediator.rentRoom(20.2000)); }}Copy the code

conclusion

After learning the design principles, a word is summed up as a class or a method, only do one thing.

DEMO