设计模式 - 简单工厂模式

2020-06-29 15:17:24 浏览数 (1)

正文共 2763 字

阅读时长:5-7 min

问题引入:

慵懒的假期,躺在沙发上的你突然想吃苹果。

苹果,从哪里来呢?

1 出门去种植,等待结果

2 去超市购买

想了想,还是去超市购买方便,自己种出来只能给儿子孙子吃了。

在这个问题中,沙发上的你,是苹果对象的使用者。超市(果农场)是苹果对象的生产者,可以理解为工厂。

如果明天又想吃菠萝,草莓,怎么办呢?从工厂拿,多方便。

那么拿的时候就要判断你想要的水果名字,找到并返回该水果对象。

将这个过程用传统代码表示,客户端:

代码语言:javascript复制
public Fruit getFruit(String fruitName){
    Fruit fruit;
        if("apple".equals(fruitName)){
              fruit = new AppleFruit();
         }else if("pineapple".equals(fruitName)){
              fruit = new PineappleFruit();
         }else if("Strawberry".equals(fruitName)){
              fruit = new StrawberryFruit();
         }
    return fruit;
}
......

在一个主函数中完成所有的功能,水果类,调用关系等。当有新水果增加或去掉水果时,需要重新修改这一大段代码。

接下来就来看看一种设计模式 :

简单工厂模式:

它是一种创建型模式。创建型模式:只关注对象的创建过程。

创建什么(what)

由谁创建(who)

何时创建(when)

将对象的创建和使用分离,客户端在使用对象时,无需关心对象创建的细节过程。在一定程度上降低系统耦合度。

简单工厂模式定义:

定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。

角色:

Factory 简单工厂

Product 抽象产品

ConcreteProduct 具体产品

要点:需要什么?只需要传入一个正确的参数,就可以获取想要的对象,而无需知道其创建细节

上述需求的简单工厂模式下的类图:

水果接口:

只需要定义一个抽象的水果接口,具体的水果,由具体的水果类来完成。

代码语言:javascript复制
package com.sample.simplefactorypattern;
public interface Fruit {
  public void tipInfo();
}

具体水果实现类:

该实现类实现 Fruit 接口,并在自己的方法中完成相应的算法操作。

即每一个类都实现自己的 tipInfo 方法。

代码语言:javascript复制
package com.sample.simplefactorypattern;
public class AppleFruit implements Fruit {
    @Override
    public void tipInfo() {
          System.out.print("山东红富士");
          System.out.println("苹果已送达");
    }
}

package com.sample.simplefactorypattern;
public class PineappleFruit implements Fruit {
      @Override
      public void tipInfo() {
             System.out.print("酸酸甜甜的");
             System.out.println("菠萝已送达");
      }
}

package com.sample.simplefactorypattern;
public class StrawberryFruit implements Fruit {
      @Override
      public void tipInfo() {
                System.out.print("红里透蜜的");
                System.out.println("草莓已送达");
      }
 }

简单工厂类:

在工厂中,需要对客户端传入的参数进行比较核对,查看工厂是否能生成相应的对象。如果可以,则返回对应对象。

同时缺点显而易见,当具体产品类多时,出现大量 if... else 循环。

代码语言:javascript复制
package com.sample.simplefactorypattern;
public class SimpleFruitFactory {
      public static Fruit createFruit(String name){
          if("apple".equalsIgnoreCase(name)){
                    return new AppleFruit();
           }else if("pineapple".equalsIgnoreCase(name)){
                    return new PineappleFruit();
           }else if("strawberry".equalsIgnoreCase(name)){
                     return new StrawberryFruit();
           }else {
                     return null;
           }
      }
 }

客户端类:

在客户端中,只需要传入一个参数,通过简单工厂类,调用生产(创造)对象的方法,就可以获取到相应对象。

代码语言:javascript复制
package com.sample.simplefactorypattern;
public class Client {
      public void getFruit(String name){
              Fruit fruit;
              fruit = SimpleFruitFactory.createFruit(name);
              if(fruit != null) {
                      fruit.tipInfo();
               }else{
                      System.out.println("该水果已售完,请等待。");
               }
       }
       
       public static void main(String[] args) {
             Client client = new Client();
             client.getFruit("apple");
             client.getFruit("pineapple");
             client.getFruit("strawberry");
             client.getFruit("banana");
        }
}

运行效果:

项目目录:

当有新的水果种类需求时,通过新的类实现 Fruit 接口即可,在简单工厂类 simpleFruitFactory 类中仍然有大量的 if ... else 判断,客户端在调用时,只需要指定一个参数就可以

该模式并不完全符合开闭原则,比传统代码有了独立结构,没有在客户端进行复杂修改。

注:简单工厂模式并不属于常用的 23 种设计模式。

简单工厂模式优点:

实现了对责任的分割,提供了专门的工厂类用于创建对象,客户端只消费产品;

客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类对应的参数即可。对于复杂的类名,可以简单的符号代替,减少记忆量。

简单工厂模式缺点:

工厂类是该模式下的核心,一旦崩溃,全局皆输;

增加了系统中类的个数,一定程度上加大了维护难度;

不利于系统扩展,一旦添加新产品,需要修改工厂类,不符合开闭原则;

对了,他并不完美,因为还有他的升级版,工厂模式,我们下篇文章见。

好了我的读者朋友,简单工厂设计模式介绍到这里,如有疑问,欢迎与我沟通交流。

感谢阅读,感谢陪伴。还没关注的,记得关注➕一下。

表情包来源于网络,侵删。谢谢。

0 人点赞