Design mode [appearance/facade mode], you will never know how many things are behind the door if you don't open the door

1. What is appearance mode (facade mode)

外观模式也叫门面模式, is a pattern that makes multiple complex subsystems more accessible by providing a consistent interface to them. The pattern like 对外有一个统一接口,外部应用程序不用关心内部子系统的具体的细节this would go greatly 降低应用程序的复杂度,提高了程序的可维护性. Its main feature is that it defines a high-level interface, which makes the subsystem easier to use, and belongs to the structural mode.

The Facade mode is a typical application of "Dimit's Law".

1. The structure of appearance mode

insert image description here

Appearance mode mainly includes 2 roles:

  • Appearance role (Facade): also known as the facade role, the unified external interface of the system;
  • Subsystem role (SubSystem): There can be one or more SubSystems at the same time. Each SubSystem is not a single class, but a collection of classes. SubSystem does not know the existence of Facade. For SubSystem, Facade is just another client (that is, Facade is transparent to SubSystem).

2. Usage scenarios

In fact, in our daily coding work, we are using a large number of appearance patterns intentionally or unintentionally. Whenever a high-level module needs to schedule multiple subsystems (more than 2 class objects), we will consciously create a new class to encapsulate these subsystems. , providing a simplified interface, making it easier for high-level modules to indirectly call the functions of these subsystems. Especially at this stage, various third-party SDKs and various open source libraries will most likely use the appearance mode. Especially the more convenient you think to call, the appearance mode is generally used more.

  • When building hierarchical systems, using the facade pattern to define entry points for each layer in a subsystem simplifies dependencies between subsystems.
  • When a complex system has many subsystems, the appearance mode can design a simple interface for the system to be accessed by the outside world.
  • When there is a large connection between the client and multiple subsystems, the introduction of the facade pattern can separate them, thereby improving the independence and portability of the subsystems.

3. Advantages and disadvantages of appearance mode

advantage:

  • It simplifies the calling process of the client, and does not need to know the subsystem in depth, so as to prevent risks to the subsystem.
  • Reduce system dependencies and loose coupling.
  • Better division of access levels improves security.
  • Follow Dimit's law, the principle of least knowledge.

shortcoming:

  • When adding subsystems and extending the behavior of subsystems, it may be easy to bring unknown risks (such as transactions).
  • Does not comply with the open-closed principle.
  • Some cases may violate the single responsibility principle.

4. Precautions for Appearance Mode

We know that the "communication" between classes, modules, and systems is generally done through interface calls. The quality of the interface design directly affects whether the classes, modules, and systems are easy to use. Therefore, we have to spend more time on interface design. I often say, 完成接口设计,就相当于完成了一半的开发任务. As long as the interface is well designed, the code is not much worse.

If the interface granularity is designed too large, it is not good if it is too small. If it is too large, the interface will not be reusable, and if it is too small, the interface will not be easy to use. In actual development, the reusability and ease of use of the interface require a "delicate" trade-off. In response to this problem, one of my basic handling principles is, 尽量保持接口的可复用性,但针对特殊情况,允许提供冗余的门面接口,来提供更易用的接口.

When maintaining a large legacy system, the system may have become very difficult to maintain and expand. At this time, you can consider developing a Facade class for the new system to provide a clearer and simpler interface for the legacy system, allowing the new system to communicate with the Facade class. Interaction, improve reusability.

However, the appearance pattern cannot be used too much or unreasonably. It is necessary to judge the necessity of using the appearance pattern. The use of the appearance pattern is to make the system layered and facilitate the purpose of maintenance.

Two, examples

1. General writing method of appearance mode

// 外观角色 Facade
public class Facade {
    
    
    private SubSystemA a = new SubSystemA();
    private SubSystemB b = new SubSystemB();
    private SubSystemC c = new SubSystemC();

    // 对外接口
    public void do() {
    
    
        this.a.doA();
        this.b.doB();
        this.c.doC();
    }
}
// 子系统
public class SubSystemA {
    
    
    public void doA() {
    
    
        System.out.println("doing A stuff");
    }
}
// 子系统
public class SubSystemB {
    
    
    public void doB() {
    
    
        System.out.println("doing B stuff");
    }
}
// 子系统
public class SubSystemC {
    
    
    public void doC() {
    
    
        System.out.println("doing C stuff");
    }
}

When multiple subsystems need to operate at the same time, use a Facade to provide an external interface:

Facade facade = new Facade();
facade.do(); // doA + doB + doC

2. Smart home case

Xiao Ming's grandfather is 60 years old and lives alone at home: every time he needs to turn on the lights, turn on the TV, and turn on the air conditioner; turn off the lights, turn off the TV, and turn off the air conditioner when he sleeps; it is more troublesome to operate. So Xiao Ming bought a smart speaker for his grandfather, who can directly control the opening and closing of these smart home appliances through voice. The class diagram is as follows:

insert image description here

//灯类
public class Light {
    
    
	public void on() {
    
    
		System.out.println("打开了灯....");
	}
	public void off() {
    
    
		System.out.println("关闭了灯....");
	}
}
//电视类
public class TV {
    
    
	public void on() {
    
    
		System.out.println("打开了电视....");
	}
	public void off() {
    
    
		System.out.println("关闭了电视....");
	}
}
//空调类
public class AirCondition {
    
    
	public void on() {
    
    
		System.out.println("打开了空调....");
	}
	public void off() {
    
    
		System.out.println("关闭了空调....");
	}
}
//智能音箱
public class SmartAppliancesFacade {
    
    
	private Light light;
	private TV tv;
	private AirCondition airCondition;
	public SmartAppliancesFacade() {
    
    
		light = new Light();
		tv = new TV();
		airCondition = new AirCondition();
	}
	public void say(String message) {
    
    
		if(message.contains("打开")) {
    
    
			on();
		} else if(message.contains("关闭")) {
    
    
			off();
		} else {
    
    
			System.out.println("我还听不懂你说的!!!");
		}
	}
	//起床后一键开电器
	private void on() {
    
    
		System.out.println("起床了");
		light.on();
		tv.on();
		airCondition.on();
	}
	//睡觉一键关电器
	private void off() {
    
    
		System.out.println("睡觉了");
		light.off();
		tv.off();
		airCondition.off();
	}
}
//测试类
public class Client {
    
    
	public static void main(String[] args) {
    
    
		//创建外观对象
		SmartAppliancesFacade facade = new SmartAppliancesFacade();
		//客户端直接与外观对象进行交互
		facade.say("打开家电");
		facade.say("关闭家电");
	}
}

3. The case of exchanging points for gifts

A mall system involves the call of points system, payment system, logistics system and other excuses. If all interface calls are sent by the front end to call the existing interface, it will increase the difficulty of front-end developers, and increase some network requests to affect page performance.

At this time, you can take advantage of the facade model. All the ready-made interfaces are integrated into one class, and the backend provides a unified interface for the frontend to call, so that the frontend developers do not need to care about the business relationship of each interface, but only need to focus on page interaction.

// 实体类
public class GiftInfo {
    
    

    private String name;

    public GiftInfo(String name) {
    
    
        this.name = name;
    }

    public String getName() {
    
    
        return name;
    }
}
// 校验积分
public class QualifyService {
    
    

    public boolean isAvailable(GiftInfo giftInfo){
    
    
        System.out.println("校验" +giftInfo.getName() + "积分通过,库存通过。");
        return true;
    }
}

// 扣减积分
public class PaymentService {
    
    

    public boolean pay(GiftInfo giftInfo){
    
    
        System.out.println("扣减" + giftInfo.getName() + " 积分成功");
        return true;
    }
}

// 物流系统
public class ShippingService {
    
    
    public String delivery(GiftInfo giftInfo){
    
    
        System.out.println(giftInfo.getName() + "进入物流系统");
        String shippingNo = "666";
        return shippingNo;
    }
}
// 使用Facade整合
public class FacadeService {
    
    
    private QualifyService qualifyService = new QualifyService();
    private PaymentService paymentService = new PaymentService();
    private ShippingService shippingService = new ShippingService();


    public void exchange(GiftInfo giftInfo){
    
    
        if(qualifyService.isAvailable(giftInfo)){
    
    
            if(paymentService.pay(giftInfo)){
    
    
                String shippingNo = shippingService.delivery(giftInfo);
                System.out.println("物流系统下单成功,物流单号是:" + shippingNo);
            }
        }
    }
}

Test code:

FacadeServicefacadeService = new FacadeService();

GiftInfo giftInfo = new GiftInfo("《Spring 5核心原理》");

facadeService.exchange(giftInfo);

References

http://www.uml.org.cn/sjms/202105262.asp

Guess you like

Origin blog.csdn.net/A_art_xiang/article/details/130637018