设计模式 - 工厂模式

2020-06-29 15:18:10 浏览数 (3)

预计阅读时间:7--9 min

情景引入:

「男朋友女朋友男女朋友生男女」

女朋友:我不想吃你买的苹果,不想吃你买的菠萝,更不想吃苹果。不想吃,不想吃,统统不想吃!!!

男朋友:不想吃,不想吃就给我滚。(豪横)

女朋友转身...

·

·

·

(此时床上躺着一个“女朋友”)

图片来自网络,侵删

女朋友:人家想吃芒果,想吃柠檬嘛。

男朋友:what?

(努力回忆:简单工厂模式中,你要啥,给我一个名字,让工厂给送啥。现在又多了俩,那我是不是再去修改下,添加上这两个就可以了)

(但这不是办法啊,如果以后还要需求咋办...)

男朋友:来,告诉我,明天会不会又说 不想要苹果了,并让它从此消失。然后还要一堆乱七八糟的,啊。

女朋友:那不一定......

啊。

看来啊,这简单工厂模式,只满足工厂类负责创建的对象比较少的情况,否则,工厂类中的业务逻辑会太过复杂;但是,它非常适用于客户端只知道传入给工厂的参数的情况,对象如何创建的不需要关心

面对上述「男朋友·女朋友」如此变幻的需求,先用工厂模式来代替看一下。

在此之前,先加一道小菜,里氏代换原则

定义:

If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T.

俗语化:

所有引用基类(父类)的地方必须能透明地使用其子类的对象。

也就是 subtype(子类型)和subclass(子类)的不同。严格来讲,o1 和 o2 满足 subtype 才可以实现 substituted,而subtype 不易判断, subclass 更易判断,现实中就先用 subclass 代替来判断。

在软件中,能够使用基类对象,那么一定能够使用其子类对象。

工厂模式定义:

Define an interface for creating anobject, but let subclasses decide which class to instantiate.Factory Method lets a class defer instantiation to subclasses.

读不懂看下面:

定义一个用于创建对象的接口,但是让子类决定将哪一个类实例化。

工厂方法模式让一个类的实例化延迟到其子类。

它是一种类创建型模式

角色:

Product:抽象产品

ConcreteProduct:具体产品

Factory:抽象工厂

ConcreteFactory:具体工厂

类图:

代码:

产品接口,具体产品非常简单,产品接口中声明一个consume方法,具体产品中实现 consume 方法。比如打印一句“concreteProductXXX 已送到”。

工厂类负责创建对应工厂。

代码语言:javascript复制
// 假装新建了 产品接口类,具体产品类
···done···
//工厂接口
public interface Factory{
    public Product create();
      }
// 具体工厂
public class ConcreteFactory1 implements Factory{
  public Product create(){
        return new ConcreteProduct();
          }}
// 客户端调用
···
Factory factory;
Product product;
factory = new ConcreteFactory1();
product = factory.create();
product.consume();
···

本例中的类图:

本例中的代码:

产品接口 Fruit,只声明一个方法即可:

代码语言:javascript复制
package com.sample.factorypattern.product;

public interface Fruit {
    public void consume();
}

具体产品,AppleFruit类:

代码语言:javascript复制
package com.sample.factorypattern.product;

public class AppleFruit implements Fruit{

    @Override
    public void consume() {
        System.out.println("红富士苹果送到了");
    }
}

MangoFruit 类:

代码语言:javascript复制
package com.sample.factorypattern.product;

public class MangoFruit implements Fruit {
    @Override
    public void consume() {
        System.out.println("黄黄的芒果来了");
    }
}

工厂接口 Factory,同样只声明一个方法:

代码语言:javascript复制
package com.sample.factorypattern.factory;

import com.sample.factorypattern.product.Fruit;

public interface Factory {
    public Fruit create();
}

具体工厂,AppleFactory 类:

代码语言:javascript复制
package com.sample.factorypattern.factory;

import com.sample.factorypattern.product.AppleFruit;
import com.sample.factorypattern.product.Fruit;

public class AppleFactory implements Factory {
    @Override
    public Fruit create() {
        return new AppleFruit();
    }
}

芒果工厂,MangoFactory 类:

代码语言:javascript复制
package com.sample.factorypattern.factory;

import com.sample.factorypattern.product.Fruit;
import com.sample.factorypattern.product.MangoFruit;

public class MangoFactory implements Factory {
    @Override
    public Fruit create() {
        return new MangoFruit();
    }
}

客户端调用,工厂对象,产品(水果)对象,反复使用,还节省了内存:

代码语言:javascript复制
package com.sample.factorypattern;

import com.sample.factorypattern.factory.AppleFactory;
import com.sample.factorypattern.factory.Factory;
import com.sample.factorypattern.factory.MangoFactory;
import com.sample.factorypattern.product.Fruit;

public class Client {
    public static void main(String[] args){
        Factory factory;
        Fruit fruit;

        //想吃苹果
        factory = new AppleFactory();
        fruit = factory.create();
        fruit.consume();

        //想吃芒果
        factory = new MangoFactory();
        fruit = factory.create();
        fruit.consume();

    }
}

运行效果:

项目结构:

工厂模式优点:

·工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节

·能够让工厂自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部

·在系统中加入新产品时,完全符合开闭原则

缺点:

·类的个数将成对增加

·增加了系统的抽象性和理解难度

适用环境:

·客户端不知道它所需要的对象的类(客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体产品对象由具体工厂类创建)

·抽象工厂类通过其子类来指定创建哪个对象

总感觉这个模式,duangduangduang 多了好多类,活也没怎么干明白。别慌,还有它的升级版,抽象工厂模式,等我,下一篇就来了。

感谢

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

表情包资源来自网络,侵删。

原创不易

1 人点赞