【设计模式】简单工厂模式

124 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第19天,点击查看活动详情

面向接口编程

  • 每个模块负责自己的职责(单一职责原则),各个模块之间通过接口通信。
  • 每个模块对应该承诺,自己对外暴露的接口是不变的,当模块内部底层实现发生变化,其他模块是不需要知道的。这便是依赖抽象,而不是依赖实现(依赖倒置原则)。
  • 上层模块只需要知道下层暴露的接口即可,如何实现无需关心 (迪米特法则)。

相关概念

  • 产品: 类

  • 抽象产品: 抽象类/接口

  • 产品簇: 多个有内在联系或者有逻辑关系的产品

  • 产品等级:

代码演示

  • A

    • 代码

       //抽象产品
       interface Food{
           void eat();
       }
       //具体产品
       class Hamburger implements Food{
           @Override
           public void eat() {
               System.out.println("吃汉堡包!");
           }
       }
       ​
       public class AppTest {
           public static void main(String[] args) {
               Food food = new Hamburger();
               food.eat();
           }
       }
      
    • 分析

      • 这种设计很脆弱,比如当具体产品的类名Hamburger发生修改,用户中new Hamburger也需要一起改变
      • 这样,具体产品和用户的代码是耦合的
      • 我们希望具体产品如何修改,用户也应该是不知道的。也就是需要解耦。
  • B

    • 针对于A中的问题,我们进行如下改进。使用简单工厂设计模式。

    • 代码

       //抽象产品 食物
       interface Food{
           void eat();
       }
       ​
       //具体产品 汉堡包
       class Hamburger implements Food{
           @Override
           public void eat() {
               System.out.println("吃汉堡包!");
           }
       }
       //具体产品 米线
       class RiceNoodle implements  Food{
       ​
           @Override
           public void eat() {
               System.out.println("吃米线");
           }
       }
       ​
       //食物工厂
       class FoodFactory{
           //获取食物
           public static Food getFood(int type){
               Food food = null;
               switch (type){
                   case 1 :
                       food = new Hamburger();
                       break;
                   case 2 :
                       food = new RiceNoodle();
                       break;
               }
               return food;
           }
       }
       //测试
       public class AppTest {
           public static void main(String[] args) {
               FoodFactory.getFood(1).eat();
               FoodFactory.getFood(2).eat();
           }
       }
      
    • 分析

      • 优点

        • 具体产品和用户解耦。
        • 当具体产品的类名发生修改,客户无需知道。继续调用食物工厂的方法即可获取对应的对象。
        • 符合了面向接口编程(非字面意思)的思想
      • 缺点

        • 用户需要记住 数字与具体产品的映射关系。 1 -》 汉堡包 2-》米线
        • 当用户需要扩展具体产品,则需要修改食物工厂中的代码,违反了开闭原则
  • C

    • 针对于B中的问题,我们使用工厂方法模式进行改进 具体看模块-02-工厂方法模式即可。