一、使用场景

1)对象的创建需要一系列的步骤:创建某些组建的时候,可能需要获取位置、形状等信息,或者需要对某些参数进行初始化;

2)无法预知对象确切类别及其依赖关系:比如需要创建一辆奥迪A6,不清楚A6的类名及创建细节,但是你可以通过奥迪工厂,指定它生产A6这个型号;

3)希望用户能扩展你的软件库或者框架的内部组件:一个验证码工具包,实现了文字验证码。 如果想扩展新的验证方式[滑动验证码],用户只需增加该验证方式及对应的实现方法,用户在使用时,通过工厂形式生产对应的验证方式;

图 扩展新的验证方式

4)解耦:将创建实例的工作从调用方中分离出,与调用方解耦。调用方不需要具体的创建过程,只管使用;

二、工厂模式

2.1 简单工厂模式

2.1.1 模式说明

定义一个创建对象的接口,将对象的创建和本身的业务逻辑分离。

图 简单工厂模式

2.1.2 代码实现

public class Audi {
    String name;
}
public class A6Audi extends Audi{

    public A6Audi() {
        name = "奥迪A6";
    }

}
public class A8Audi extends Audi{

    public A8Audi() {
        name = "奥迪A8";
    }

}
public class AudiFactory {

    public Audi createAudiCar(int type) {
        Audi audi = null;
        switch (type) {
            case 0:
                audi = new A6Audi();
                break;
            case 1:
                audi = new A8Audi();
                break;
            default:
                audi = null;
        }
        return audi;
    }

}
public class Audi4S {

    private static AudiFactory factory = new AudiFactory();

    public static void main(String[] args) {
        //用户选车
        int type = new Random().nextInt(3);
        //工厂生产
        Audi audi = factory.createAudiCar(type);
        //汽车交付
        System.out.println(audi == null ? "该型号停产了" : audi.name);
    }

}

内部类实现简单工厂模式:

/**
 * 内部类实现简单工厂模式-奥迪车
 */
public interface Audi {

    public void drive();

}

public class AudiFactory {

    private AudiFactory() {}

    public static Audi buildA6() {
        return new Audi() {
            @Override
            public void drive() {
                System.out.println("Hello A6!");
            }
        };
    }

    public static Audi buildA8() {
        return new Audi() {
            @Override
            public void drive() {
                System.out.println("Hello A8!");
            }
        };
    }

}

public class Audi4S {

    public static void main(String[] args) {
        Audi a6 = AudiFactory.buildA6();
        Audi a8 = AudiFactory.buildA8();
        a6.drive();
        a8.drive();
    }

}

2.1.3 优缺点

优点:1)外界可不必管这些对象如何创建及如何组织的,明确了各自的职责和权利,有利于整个软件体系结构的优化;

缺点:1)违反了高内聚责任分配原则,将全部创建逻辑集中到一个工厂类中;2)它所能创建的类只能是事先考虑的,如果需要添加新的类,就需要改变工厂类;3)当具体类不断增多的时候,很难避免模块功能的蔓延,对系统的维护和扩展非常不利;

这种模式一般只在很简单的情况下应用,在实际开发中使用较少。

2.2 工厂方法模式

2.2.1 模式说明

将工厂抽象化,定义了一个创建对象的接口,每增加新的产品,只需增加该产品以及对应的工厂实现类。

图 工厂方法模式 

2.2.2 代码实现

public class FaceMask {

    String name;

}
public class N97FaceMask extends FaceMask{

    public N97FaceMask() {
        this.name = "N97口罩";
    }

}
public class OrdinaryFaceMask extends FaceMask{

    public OrdinaryFaceMask() {
        this.name = "普通口罩";
    }

}
public interface Factory {

    FaceMask create();

}
public class N97Factory implements Factory{

    @Override
    public FaceMask create() {
        return new N97FaceMask();
    }

}
public class OrdinaryFactory implements Factory{

    @Override
    public FaceMask create() {
        return new OrdinaryFaceMask();
    }

}
public class FaceMaskShop {

    final static Factory n97Factory = new N97Factory();
    final static Factory ordinaryFactory = new OrdinaryFactory();

    public static void main(String[] args) {
        FaceMask n97 = n97Factory.create();
        FaceMask ordinary = ordinaryFactory.create();
        System.out.println(n97.name);
        System.out.println(ordinary.name);
    }

}

2.2.3 优缺点

优点:1)良好的扩展性,当系统需要加入新的产品时,无需修改抽象工厂,也无需修改其他的具体工厂和具体产品,只要添加一个具体的产品和一个具体的实现工厂就可完成工厂的扩展;

缺点:1)每增加一个产品,都需增加一个具体产品类和实现工厂类,使得系统中类的个数成倍增加;

2.3 抽象工厂模式

2.3.1 概念介绍

产品等级:产品的继承结构,比如苹果手机,它有iPhone13、iPhone 11等一系列的子类,那么苹果手机和它的子类就构成了一个产品等级;

产品族:由同一家公司生产,位于不同产品等级中的一组产品。比如 MacBook 2021款 与 iPhone13

图 产品族与产品等级

2.3.2 模式说明

主要用于创建相关对象的家族。当一个产品族需要被设计在一起工作时,通过抽象工厂模式,能保证客户端始终只使用同一个家族中的对象。

图 抽象工厂模式

2.3.3 代码实现

public class IPhone {

    /**
     * 型号
     */
    String model;

}
public class IPhone11 extends IPhone{

    public IPhone11() {
        this.model = "苹果11";
    }

}
public class IPhone13 extends IPhone{

    public IPhone13() {
        this.model = "苹果13";
    }

}
public class MacBook {

    /**
     * 型号
     */
    String model;

}
public class MacBook2017 extends MacBook{

    public MacBook2017() {
        this.model = "MacBook2017";
    }

}
public class MacBook2021 extends MacBook{

    public MacBook2021() {
        this.model = "MacBook2021";
    }

}
public interface Factory {

    IPhone createIPhone();

    MacBook createMacBook();

}
public class Factory2017 implements Factory{

    @Override
    public IPhone createIPhone() {
        return new IPhone11();
    }

    @Override
    public MacBook createMacBook() {
        return new MacBook2017();
    }

}
public class Factory2021 implements Factory{

    @Override
    public IPhone createIPhone() {
        return new IPhone13();
    }

    @Override
    public MacBook createMacBook() {
        return new MacBook2021();
    }

}
public class AppleShop {

    private final static Factory factory2017 = new Factory2017();
    private final static Factory factory2021 = new Factory2021();

    public static void main(String[] args) {
        IPhone iPhone11 = factory2017.createIPhone();
        MacBook macBook2017 = factory2017.createMacBook();
        System.out.println(iPhone11.model + " + " + macBook2017.model);

        IPhone iPhone13 = factory2021.createIPhone();
        MacBook macBook2021 = factory2021.createMacBook();
        System.out.println(iPhone13.model + " + " + macBook2021.model);
    }

}

2.3.4 优缺点

优点:1)拥有多个抽象产品类和一个抽象工厂类;2)保证客户端始终只使用同一个产品族中的产品;

缺点:1)如果需要添加一个新产品族对象时,需要更改接口及其下所有的类;

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐