[Nine] Design Patterns ~~~ Structural Patterns ~~~ Appearance Patterns (Java)

[Learning Difficulty: ★☆☆☆☆, Frequency of Use: ★★★★★]

4.1. Pattern Motivation

       I don’t know if you have compared the difference between making tea by yourself and drinking tea in a teahouse. If you make tea by yourself, you need to prepare tea leaves, tea sets and boiling water by yourself, as shown in Figure 1 (A). However, drinking tea in a teahouse is the simplest The way is to tell the waiter what kind of tea you want a cup of tea, is it Tieguanyin, Biluochun or West Lake Longjing? Because there are waiters in the teahouse, customers do not need to directly interact with tea leaves, tea sets, boiling water, etc. The whole process of making tea is completed by the waiters, and customers only need to interact with the waiters. The whole process is very simple and trouble-free, as shown in Figure 1(B) :
insert image description here

       In software development, sometimes in order to complete a more complex function, a client class needs to interact with multiple business classes, and these business classes that need to interact often appear as a whole, because there are many classes involved, resulting in The code is more complicated when used. At this time, a role like a waiter is especially needed, which is responsible for interacting with multiple business classes, and the client class only needs to interact with this class. The appearance mode realizes this function by introducing a new appearance class (Facade). The appearance class acts as a "waiter" in the software system. It provides a unified entrance for calling multiple business classes and simplifies the relationship between classes. interaction between. In the facade mode, those business classes that need to interact are called subsystems . If there is no appearance class, then each client class needs to perform complex interactions with multiple subsystems, and the coupling degree of the system will be very large, as shown in Figure 2 (A); after the appearance class is introduced, the client class only needs to directly Interacting with the appearance class, the original complex reference relationship between the client class and the subsystem is realized by the appearance class, thereby reducing the coupling degree of the system, as shown in Figure 2(B).

insert image description here

       In the appearance mode, the communication between the outside of a subsystem and its inside is carried out through a unified appearance class. The appearance class separates the client class from the internal complexity of the subsystem, so that the client class only needs to deal with the appearance role and does not need to Interact with many objects within the subsystem.

4.2. Schema Definition

       Facade Pattern: The communication between the outside and a subsystem must be carried out through a unified facade object, providing a consistent interface for a set of interfaces in the subsystem. The facade pattern defines a high-level interface, which makes this interface Subsystems are easier to use. Appearance mode, also known as facade mode, is an object structure mode.

4.3. Schema structure

Facade mode contains the following roles:

  • Facade: Facade role , its methods can be called on the client side, and the functions and responsibilities of the related (one or more) subsystems can be known in the facade role; under normal circumstances, it will send all requests from the client It is delegated to the corresponding subsystem and passed to the corresponding subsystem object for processing.
  • SubSystem: Subsystem role , there can be one or more subsystem roles in a software system, each subsystem may not be a single class, but a collection of classes, which implement the functions of the subsystem; each subsystem can Called directly by the client, or called by the appearance role, it processes the request passed by the appearance class; the subsystem does not know the existence of the appearance, and for the subsystem, the appearance role is just another client.

insert image description here

4.4. Timing diagram

insert image description here

4.5. Code Analysis

       A software company wants to develop a file encryption module that can be applied to multiple software. This module can encrypt the data in the file and store the encrypted data in a new file. The specific process includes three parts, namely Read the source file, encrypt, and save the encrypted file. Among them, reading and saving the file are implemented using a stream, and the encryption operation is implemented through a modulo operation. These three operations are relatively independent. In order to achieve independent code reuse and make the design more in line with the single responsibility principle, the business codes of these three operations are encapsulated in three different classes.

       Now use appearance mode to design the file encryption module.
insert image description here

       In Figure 4, EncryptFacade acts as a facade class, and FileReader, CipherMachine, and FileWriter act as subsystem classes.

4.5.1 Production

FileReader: file reading class, which acts as a subsystem class.
CipherMachine: Data encryption class, which acts as a subsystem class.
FileWriter: A file saving class that acts as a subsystem class.
EncryptFacade: Encrypted facade class, which acts as a facade class.
package com.zyz.com;

/**
 * @author zyz
 * @version 1.0
 * @data 2023/5/15 22:31
 * @Description:
 */
class EncryptFacade {
    
    
    /**
     * 维持对其他对象的引用
     */
    private FileReader fileReader;
    private CipherMachine encryptFacade;
    private FileWriter fileWriter;

    public EncryptFacade(){
    
    
        fileReader = new FileReader();
        encryptFacade = new CipherMachine();
        fileWriter = new FileWriter();
    }

    /**
     *  调用其他对象的业务方法
     */
    public void FileEncrypt(){
    
    
        fileReader.Read();
        encryptFacade.Encrypt();
        fileWriter.Write();
    }


}


//文件读取类,充当子系统类

class FileReader{
    
    
    public void Read(){
    
    
        System.out.println("文件读取类子系统:读取文件...");
    }
}

//数据加密类,充当子系统类

class CipherMachine{
    
    
    public void Encrypt(){
    
    
        System.out.println("数据加密类子系统:加密文件...");
    }
}


//文件保存类,充当子系统类

class FileWriter{
    
    
    public void Write(){
    
    
        System.out.println("文件保存类子系统:保存文件...");
    }
}

4.5.2 Client

package com.zyz.com;

/**
 * @author zyz
 * @version 1.0
 * @data 2023/5/15 22:45
 * @Description: 客户端
 */
public class Client {
    
    
    public static void main(String[] args) {
    
    
        EncryptFacade facade = new EncryptFacade();
        facade.FileEncrypt();
    }
}

4.5.3 Test results

insert image description here

4.6. Pattern Analysis

       According to the "Single Responsibility Principle", dividing a system into several subsystems in software is beneficial to reduce the complexity of the entire system. A common design goal is to minimize the communication and interdependence between subsystems, and to achieve this goal One of the ways is to introduce a facade object, which provides a simple and single entry point for subsystem access. - Appearance mode is also the embodiment of "Dimit's Law". By introducing a new appearance class, the complexity of the original system can be reduced, and the coupling degree between the client class and the subsystem class can be reduced. - Facade mode requires that the communication between the outside of a subsystem and its inside be carried out through a unified façade object, and the façade class separates the client from the internal complexity of the subsystem, so that the client only needs to deal with the façade object instead of Interact with many objects within the subsystem. - The purpose of facade mode is to reduce the complexity of the system. - The Appearance mode has greatly improved the convenience of the client, so that the client does not need to care about the working details of the subsystem, and can call related functions through the appearance role.

4.7. Examples

4.8. Advantages

Advantages of Facade Mode

  • Shielding subsystem components from clients reduces the number of objects handled by clients and makes the subsystem easier to use. By introducing the Facade pattern, the client code will be very simple with few objects associated with it.
  • The loose coupling relationship between the subsystem and the client is realized, which makes the component change of the subsystem not affect the client class that calls it, and only needs to adjust the appearance class.
  • It reduces compilation dependencies in large software systems and simplifies the process of porting systems between different platforms, because compiling one subsystem generally does not require compiling all other subsystems. The modification of one subsystem has no effect on other subsystems, and the internal changes of the subsystem will not affect the appearance objects.
  • It just provides a unified entrance to access the subsystem, and does not affect the user's direct use of the subsystem class.

4.9. Disadvantages

Disadvantages of facade mode

  • The use of subsystem classes by customers cannot be well restricted. If there are too many restrictions on customers' access to subsystem classes, the variability and flexibility will be reduced.
  • Without introducing an abstract facade class, adding a new subsystem may require modifying the source code of the facade class or the client, which violates the "open-closed principle".

4.10. Applicable environment

Facade mode can be used in the following situations:

  • Façade pattern can be used when you want to provide a simple interface to a complex subsystem. This interface can meet the needs of most users, and users can also bypass the facade class to directly access the subsystem.
  • There are significant dependencies between client programs and multiple subsystems. The introduction of facade classes decouples subsystems from clients and other subsystems, which can improve the independence and portability of subsystems.
  • In the hierarchical structure, the appearance mode can be used to define the entrance of each layer in the system. There is no direct connection between layers, but the connection is established through appearance classes to reduce the coupling degree between layers.

4.11. Schema Application

4.12. Schema Extensions

A system has multiple appearance classes
       In the appearance mode, usually only one appearance class is needed, and this appearance class has only one instance, in other words it is a singleton class. In many cases, in order to save system resources, the appearance class is generally designed as a singleton class. Of course, this does not mean that there can only be one appearance class in the entire system. Multiple appearance classes can be designed in a system, and each appearance class is responsible for interacting with some specific subsystems and providing users with corresponding business functions.

Don't try to add new behavior to the subsystem through the facade class.
       Don't add new behavior to the subsystem by inheriting a facade class. This approach is wrong. The purpose of the appearance mode is to provide a centralized and simplified communication channel for the subsystem, rather than adding new behaviors to the subsystem. The addition of new behaviors should be achieved by modifying the original subsystem class or adding a new subsystem class , cannot be achieved through the facade class.

Facade pattern and Dimit's law
       Facade pattern creates a façade object, which minimizes the number of collaborating partners belonging to a subsystem involved by the client, so that the interaction between the client and the objects inside the subsystem is controlled by the façade object replace. The appearance class acts as a "third party" between the client class and the subsystem class, reducing the coupling between the client class and the subsystem class. The appearance mode is to achieve code refactoring to meet the requirements of "Dimit's Law" A powerful weapon.


       The biggest disadvantage of the introduction of the abstract appearance class is that it violates the "opening and closing principle". When adding a new subsystem or removing a subsystem, the appearance class needs to be modified. This problem can be solved to a certain extent by introducing an abstract appearance class . Clients program against the abstract facade class. For new business requirements, the original appearance class is not modified, but a new specific appearance class is correspondingly added, and the new specific appearance class is associated with the new subsystem object. At the same time, the source code is not modified and replaced by modifying the configuration file. The purpose of the appearance class.

4.13. Summary

  • In the appearance mode, the communication between the outside and a subsystem must be carried out through a unified appearance object, which provides a consistent interface for a set of interfaces in the subsystem. The appearance mode defines a high-level interface, which makes the subsystem Easier to use. Appearance mode, also known as facade mode, is an object structure mode.
  • The façade mode contains two roles: the façade role is a role that is directly invoked on the client side. In the façade role, the functions and responsibilities of the relevant (one or more) subsystems can be known, and it delegates all requests sent from the client. Go to the corresponding subsystem and pass it to the corresponding subsystem object for processing; there can be one or more subsystem roles in the software system at the same time, and each subsystem may not be a separate class, but a collection of classes, which implements Subsystem functions.
  • Facade mode requires that the communication between the outside of a subsystem and its inside be carried out through a unified façade object, and the façade class separates the client from the internal complexity of the subsystem, so that the client only needs to deal with the façade object instead of the Many objects within the subsystem deal with each other.
  • The main advantage of the appearance mode is that it shields the subsystem components from the client, reduces the number of objects processed by the client and makes the subsystem easier to use, it realizes the loose coupling relationship between the subsystem and the client, and reduces the complexity in large software systems. Compilation dependency simplifies the process of porting the system between different platforms; its disadvantage is that it cannot well restrict customers from using subsystem classes, and without introducing abstract appearance classes, adding new subsystems may require modifying the appearance The source code of a class or client violates the "open-closed principle".
  • Applicable situations of the appearance mode include: to provide a simple interface for a complex subsystem; there is a large dependency between the client program and multiple subsystems; in the hierarchical structure, it is necessary to define the entry of each layer in the system, so that the layer There is no direct relationship with the layer.

4.14. Extensions

       In the standard structural diagram of the appearance pattern, if it is necessary to add, delete or replace the subsystem class interacting with the appearance class, the source code of the appearance class or the client must be modified, which will violate the principle of opening and closing, so it can be solved by introducing an abstract appearance class This problem can be solved to a certain extent by improving the system. After the abstract appearance class is introduced, the client can program against the abstract appearance class. For new business requirements, there is no need to modify the original appearance class, but a new concrete appearance class is correspondingly added, and the new concrete appearance class is associated with the new Subsystem objects, and at the same time modify the configuration file to achieve the purpose of not modifying any source code and replacing the appearance class.

       Let's use a specific example to learn how to use the abstract appearance class:
       If you need to replace an encryption class in the application example "File Encryption Module", you will no longer use the original encryption class CipherMachine based on the modulo operation, but instead use the shift-based The new encryption class NewCipherMachine for operation, its code is as follows:

using System;
 
namespace FacadeSample
{
    
    
    class NewCipherMachine
    {
    
    
        public string Encrypt(string plainText) 
        {
    
    
		    Console.Write("数据加密,将明文转换为密文:");
		    string es = "";
		    int key = 10;//设置密钥,移位数为10
            char[] chars = plainText.ToCharArray();
            foreach(char ch in chars) 
            {
    
    
                int temp = Convert.ToInt32(ch);
                //小写字母移位
			    if (ch >= 'a' && ch <= 'z') {
    
    
				    temp += key % 26;
			        if (temp > 122) temp -= 26;
                    if (temp < 97) temp += 26;
			    }
                //大写字母移位
			    if (ch >= 'A' && ch <= 'Z') {
    
    
                    temp += key % 26;
                    if (temp > 90) temp -= 26;
                    if (temp < 65) temp += 26;
			    }
                es += ((char)temp).ToString();
		    }
            Console.WriteLine(es);
		    return es;
	    }
    }
}

       If no new appearance class is added, the encryption class can only be replaced by modifying the source code of the original appearance class EncryptFacade, changing the original reference to the CipherMachine type object to a reference to the NewCipherMachine type object, which violates the open Because of the principle of closure, it is necessary to change the reference to the subsystem object by adding a new appearance class.

       If a new appearance class NewEncryptFacade is added to interact with the FileReader class, FileWriter class and the newly added NewCipherMachine class, although the original system class library does not need to be modified, because the client code was originally programmed for the EncryptFacade class, now it needs to Changed to the NewEncryptFacade class, so the client source code needs to be modified.

       How to use the new appearance class without modifying the client code? One of the solutions is: introduce an abstract appearance class, the client programs for the abstract appearance class, and then determine the specific appearance class at runtime, the structure diagram of the file encryption module after the introduction of the abstract appearance class is shown in Figure 5:
insert image description here

                      Figure 5 The structure diagram of the file encryption module after introducing the abstract appearance class

       In Figure 5, the client class Client is programmed for the abstract appearance class AbstractEncryptFacade, and the AbstractEncryptFacade code is as follows:

namespace FacadeSample
{
    
    
    abstract class AbstractEncryptFacade
    {
    
    
        public abstract void FileEncrypt(string fileNameSrc, string fileNameDes);
    }
}
新增具体加密外观类NewEncryptFacade代码如下:
namespace FacadeSample
{
    
    
    class NewEncryptFacade : AbstractEncryptFacade
    {
    
    
        private FileReader reader;
        private NewCipherMachine cipher;
        private FileWriter writer;
 
        public NewEncryptFacade()
        {
    
    
            reader = new FileReader();
            cipher = new NewCipherMachine();
            writer = new FileWriter();
        }
 
        public override void FileEncrypt(string fileNameSrc, string fileNameDes)
        {
    
    
            string plainStr = reader.Read(fileNameSrc);
            string encryptStr = cipher.Encrypt(plainStr);
            writer.Write(encryptStr, fileNameDes);
        }
    }
}

The class name of the specific appearance class is stored in the configuration file App.config, and the code is as follows:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="facade" value="FacadeSample.NewEncryptFacade"/>
  </appSettings>
</configuration>

The client test code is modified as follows:

using System;
using System.Configuration;
using System.Reflection;
 
namespace FacadeSample
{
    
    
    class Program
    {
    
    
        static void Main(string[] args)
        {
    
    
            AbstractEncryptFacade ef; //针对抽象外观类编程
            //读取配置文件
            string facadeString = ConfigurationManager.AppSettings["facade"];
            //反射生成对象
            ef = (AbstractEncryptFacade)Assembly.Load("FacadeSample"). CreateInstance (facadeString);
            ef.FileEncrypt("src.txt", "des.txt");
            Console.Read();
        }
    }
}

Compile and run the program, the output results are as follows:
read the file, get the plaintext: Hello world!
data encryption, convert the plaintext to ciphertext: Rovvy gybvn!
save the ciphertext, and write to the file.
The original appearance class EncryptFacade also needs to be a subclass of the abstract appearance class AbstractEncryptFacade. When replacing a specific appearance class, only the configuration file needs to be modified, and the source code does not need to be modified, which conforms to the principle of opening and closing.

Guess you like

Origin blog.csdn.net/weixin_43304253/article/details/130944825