优雅的程序设计:掌握门面模式的奥秘_设计模式

前言

在软件开发中,设计模式扮演着至关重要的角色,而门面模式则是其中的瑰宝。如果你渴望简化复杂的系统、提高代码的可维护性和可扩展性,那么这篇文章是必读之选。它深入剖析了门面模式的核心原理,通过实战案例展示了其在现实场景中的应用。无论你是初学者还是经验丰富的开发者,你都将从中获得启发和实用的指导。让我们一起探索门面模式的奥秘,为软件开发的成功铺就坚实的基石!

什么是门面模式

门面模式是一种结构型设计模式,它提供了一个统一的接口,用来访问子系统中的一群接口。它定义了一个高层接口,让子系统更容易使用。这种模式常用于将一个复杂的子系统封装成一个简单的接口,使得客户端可以方便地使用子系统的功能,而不需要了解子系统的具体实现细节。

门面模式的特点

  1. 代理模式能够隐藏真实对象的实现细节,使客户端无需知晓真实对象的工作方式和结构。
  2. 通过代理类来间接访问真实类,可以在不修改真实类的情况下对其进行扩展、优化或添加安全措施。
  3. 代理模式实现起来简单,易于扩展和维护,符合面向对象设计原则中的开闭原则。

门面模式的核心原理

门面模式是一种结构型设计模式,其核心原理是将复杂系统的复杂性隐藏在一个简单的接口后面,以此来简化系统的使用。在门面模式中,一个门面类(Facade)作为系统和客户端之间的接口,屏蔽了系统的复杂性,使得客户端可以通过简单的接口来访问系统的功能。门面类将系统的各个子系统组合起来,提供了一个简单而统一的接口,使得客户端可以方便地使用系统的功能,同时也保证了系统的灵活性和可扩展性。因此,门面模式是一种非常实用的设计模式,在现代软件开发中得到了广泛的应用。

门面模式(Facade Pattern)有三个核心角色:

  1. 门面角色(Facade):这是门面模式的核心,被客户角色调用。它熟悉子系统的功能,内部根据客户角色已有的需求预定了几种功能组合。
  2. 子系统角色(Subsystem):实现了子系统的功能。对于子系统角色来说,门面角色和客户角色都是未知的,它没有任何门面角色信息和链接。
  3. 客户角色(Client):这是使用门面模式的外部请求者,它通过门面角色来访问子系统,以获取所需的功能。

优雅的程序设计:掌握门面模式的奥秘_门面模式_02

门面模式如何实现

假如用门面模式来模拟实现一下去饭店点菜吃饭应该怎么实现呢?虽然去饭店吃饭这件事挺普通的,但是要想吃到饭,起码是要走这样一个流程:点餐、炒菜、上菜、收/付钱。其实这里的饭店就可以看作是一个门面角色,饭店内不同的角色:如老板、收银员、服务员、厨师等,可以看作是饭店这个门面内的子系统角色,不同的角色职责是不同的,服务员负责帮客人点餐、上菜,厨师炒菜,收银员负责收钱,但是对于客人而言,吃饭是重点,通常不会关注是谁做的、谁端上来的。

那使用门面模式怎么实现呢?UML类图如下:

优雅的程序设计:掌握门面模式的奥秘_设计模式_03

1、Restaurant:饭店类,有三个List类型的属性,分别用来表示饭店内会有厨师、服务员、收银员等不同角色的人员对象;对应还有三个可以给饭店增加三种不同角色人员的方法;最后一个方法就是饭店对外的主要职能:可以吃饭;

2、Waiter:服务员类,有两个方法:帮客人下单、上菜;

3、Cook:厨师类,有一个方法:炒菜;

4、Cashier:收银员类,有一个方法:收菜;

5、Cilent:客户端类,作为客户端,直接依赖Restaurant类,而不具体去找某个服务员或厨师;

/** 
* 服务员 
*
/@Data
@AllArgsConstructor
public class Waiter {
    private String name;

    public void placeOrder(){
        System.out.println(this.name+"->帮客人点菜");
    }

    public void serveDishes(){
        System.out.println(this.name+"->给客人上菜");
    }
}
/** * 厨师 */@Data
@AllArgsConstructor
public class Cook {
    private String name;

    public void cooking() {
        System.out.println(this.name + "->炒菜");
    }
}
/** 
* 收银员 
*/
@Data
@AllArgsConstructor
public class Cashier {
    private String name;

    public void collectMoney() {
        System.out.println(this.name + "->收钱");
    }
}
/** 
* 饭店 
*/ 
@Data
public class Restaurant {
    private String name;
    private List<Cook> cooks = new ArrayList<>();
    private List<Waiter> waiters = new ArrayList<>();
    private List<Cashier> cashiers = new ArrayList<>();

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

    public void addCooks(Cook cook) {
        this.cooks.add(cook);
    }

    public void addWaiter(Waiter waiter) {
        this.waiters.add(waiter);
    }

    public void addCashier(Cashier cashier) {
        this.cashiers.add(cashier);
    }

    private int ranomInt(Integer maxInt){
        Random random = new Random();
        return random.nextInt(maxInt);
    }
    public void eat(){
        this.waiters.get(this.ranomInt(this.waiters.size())).placeOrder();//点菜
        this.cooks.get(this.ranomInt(this.cooks.size())).cooking();//炒菜
        this.waiters.get(this.ranomInt(this.waiters.size())).serveDishes();//上菜
        System.out.println("客人->吃饭");
        this.cashiers.get(this.ranomInt(this.cashiers.size())).collectMoney();//收钱

    }
}
public class Client {    public static void main(String[] args) {        Restaurant restaurant = new Restaurant("和平饭店");        Cook cook1 = new Cook("张厨师");
        Cook cook2 = new Cook("李厨师");
        restaurant.addCooks(cook1);
        restaurant.addCooks(cook2);
        Waiter waiter1 = new Waiter("王小红");
        Waiter waiter2 = new Waiter("张小月");
        restaurant.addWaiter(waiter1);
        restaurant.addWaiter(waiter2);
        Cashier cashier1 = new Cashier("老板");
        Cashier cashier2 = new Cashier("老板娘");
        restaurant.addCashier(cashier1);
        restaurant.addCashier(cashier2);
        restaurant.eat();
    }
}

优雅的程序设计:掌握门面模式的奥秘_设计模式_04

门面模式的适用场景

门面模式适用于以下场景:

  1. 为一个复杂的子系统提供一个简单的接口,使得客户端可以方便地使用子系统的功能。
  2. 需要对一个子系统进行封装,并隐藏子系统的内部实现细节,只提供一个精简的接口供客户端使用,这样可以降低客户端与子系统的耦合度。
  3. 需要提高子系统的独立性,使得客户端不直接与子系统交互,而是通过门面角色来进行交互。
  4. 需要隔离客户端与子系统的直接交互,预防低水平人员带来的风险扩散。

总结

优点:

  1. 减少系统的相互依赖:门面模式可以让客户端只需要依赖门面对象,而与子系统无关。这样可以降低系统耦合度。
  2. 提高灵活性:通过门面角色,客户端不再直接与子系统交互,而是通过门面角色提供的精简接口来实现交互。这样,子系统的内部实现细节可以被隐藏起来,子系统如何变化对客户端来说是透明的,提高了系统的灵活性。
  3. 提高安全性:外部只能通过门面访问子系统的功能,门面没有开放的就不能访问,提高了子系统的安全性。

缺点:

  1. 不符合开闭原则。系统投产后,一旦发现错误,只能修改门面角色的代码,风险比较大。
  2. 系统的复杂性和理解难度有一定增加;

总的来说,门面模式可以简化复杂子系统的使用、隐藏实现细节、提高子系统独立性和隔离客户端与子系统的直接交互,但也存在一些缺点需要注意。在具体使用时,需要根据具体情况进行权衡,并考虑是否适合使用该模式。

写在最后

我非常推荐这篇引人入胜的文章!它深入解析了门面模式的精髓,通过实践案例让你了解如何优雅地应用门面模式,并解决复杂系统中的困难和挑战。我相信,这篇文章能够为你的职业生涯带来新的启示和思路。快来阅读并点赞,为自己的软件开发之路加油助力!