设计模式(二):几种工厂模式详解

概念

​ 工厂顾名思义就是创建产品,根据产品是具体产品还是具体工厂可分为简单工厂模式和工厂方法模式,根据工厂的抽象程度可分为工厂方法模式和抽象工厂模式。该模式用于封装和管理对象的创建,是一种创建型模式。

工厂模式分三类

1.简单工厂模式(Simple Factory)
2.工厂方法模式(Factory Method)
3.抽象工厂模式(Abstract Factory)

在《设计模式》一书中工厂模式分为两类:工厂方法模式(Factory Method)与抽象工厂模式(Abstract Factory)。将简单工厂模式(Simple Factory)看为工厂方法模式的一种特例,两者归为一类。

简单工厂模式(Simple Factory)

该模式对对象创建管理方式最为简单,因为其仅仅简单的对不同类对象的创建进行了一层薄薄的封装。该模式通过向工厂传递类型来指定要创建的对象,其UML类图如下

设计模式(二):几种工厂模式详解_第1张图片

示例

Constant

public class Constant {
   public static  String HuaWeiPhone = "HuaWeiPhone";
   public static  String ApplePhone = "ApplePhone";
}

IPhone类:手机标准规范类(AbstractProduct)

public interface AbstractFactory {
    IPhone makePhone();
}

HuaWeiPhone:制造华为手机(Product1)

public class HuaWeiPhone implements IPhone {
    public HuaWeiPhone (){
        this.make();
    }

    public void make() {
        System.out.println("make huawei phone!");
    }
}

ApplePhone:制造苹果手机 (Product2)

public class ApplePhone implements IPhone {
    public ApplePhone(){
        this.make();
    }

    public void make() {
        System.out.println("make apple phone!");
    }
}

PhoneFactory类:手机代工厂(Factory)

public class PhoneFactory {
    public IPhone makePhone(String phoneType) {
        if(phoneType.equalsIgnoreCase(Constant.HuaWeiPhone)){
            return new HuaWeiPhone();
        }
        else if(phoneType.equalsIgnoreCase(Constant.ApplePhone)) {
            return new ApplePhone();
        }
        return null;
    }
}

SimpleFactoryDemo

public class SimpleFactoryDemo {
    public static void main(String[] args) {
        PhoneFactory phoneFactory = new PhoneFactory();
        HuaWeiPhone huaWeiPhone = (HuaWeiPhone)phoneFactory.makePhone(Constant.HuaWeiPhone);
        ApplePhone applePhone = (ApplePhone)phoneFactory.makePhone(Constant.ApplePhone);
    }
}

输出

make huawei phone!
make apple phone!

工厂方法模式(Factory Method)

工厂方法模式去掉了简单工厂模式中工厂方法的静态属性,使得它可以被子类继承。这样在简单工厂模式里集中在工厂方法上的压力可以由工厂方法模式里不同的工厂子类来分担。 也就是将生成具体产品的任务分发给具体的产品工厂
工厂方法模式组成:
1)抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。
2)具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。
3)抽象产品角色:它是具体产品继承的父类或者是实现的接口。一般有抽象类或者接口来实现。
4)具体产品角色:具体工厂角色所创建的对象就是此角色的实例。由具体的类来实现。

其UML类图如下

设计模式(二):几种工厂模式详解_第2张图片

示例

AbstractFactory:生产不同产品的工厂的抽象类

public interface AbstractFactory {
    IPhone makePhone();
}

HuaWeiFactory:生产华为手机的工厂(ConcreteFactory1)

public class HuaWeiFactory implements AbstractFactory {
    public IPhone makePhone() {
        return new HuaWeiPhone();
    }
}

AppleFactory:生产苹果手机的工厂(ConcreteFactory2)

public class AppleFactory implements AbstractFactory {
    public IPhone makePhone() {
        return new ApplePhone();
    }
}

FactoryMethodDemo

public class FactoryMethodDemo {
    public static void main(String[] args) {
        AbstractFactory huaWeiFactory = new HuaWeiFactory();
        AbstractFactory appleFactory = new AppleFactory();
        huaWeiFactory.makePhone();
        appleFactory.makePhone();
    }
}

输出

make huawei phone!
make apple phone!

优点

1.更符合开-闭原则

新增一种产品时,只需要增加相应的具体产品类和相应的工厂子类即可

2.符合单一职责原则

每个具体工厂类只负责创建对应的产品

3.不使用静态工厂方法,可以形成基于继承的等级结构

缺点

1.添加新产品时,除了增加新产品类外,还要提供与之对应的具体工厂类,系统类的个数将成对增加,在一定程度上增加了系统的复杂度;同时,有更多的类需要编译和运行,会给系统带来一些额外的开销

2.由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度

3.虽然保证了工厂方法内的对修改关闭,但对于使用工厂方法的类,如果要更换另外一种产品,仍然需要修改实例化的具体工厂类

4.一个具体工厂只能创建一种具体产品

应用场景

1.当一个类不知道它所需要的对象的类时

在工厂方法模式中,不需要知道具体产品类的类名,只需要知道所对应的工厂即可

2.当一个类希望通过其子类来指定创建对象时在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,利用面向对象的多态性和里氏代换原则,在程序运行时,子类对象将覆盖父类对象,从而使得系统更容易扩展。

3.将创建对象的任务委托给多个工厂子类中的某一个,在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时再动态指定,可将具体工厂类的类名存储在配置文件或数据库中。

抽象工厂模式(Abstract Factory)

抽象工厂模式通过在AbstarctFactory中增加创建产品的接口,并在具体子工厂中实现新加产品的创建,当然前提是子工厂支持生产该产品。否则继承的这个接口可以什么也不干。

抽象工厂模式的各个角色和工厂方法模式一样

其UML类图如下

设计模式(二):几种工厂模式详解_第3张图片

Computer类:定义Computer产品的接口(AbstractComputer)

public interface Computer {
    void make();
}

HuaWeiComputer类:定义华为电脑产品(HuaWeiComputer)

public class HuaWeiComputer implements Computer {
    public HuaWeiComputer(){
        this.make();
    }

    public void make() {
        System.out.println("make huawei computer!");
    }
}

AppleComputer类:定义苹果电脑产品(AppleComputer)

public class AppleComputer implements Computer {
    public AppleComputer(){
        this.make();
    }

    public void make() {
        System.out.println("make apple computer!");
    }
}

AbstractFactory类:增加Computer产品制造接口

public interface AbstractFactory {
    IPhone makePhone();
    Computer makeComputer();
}

HuaWeiFactory类:增加小米Computer的制造(ConcreteFactory1)

public class HuaWeiFactory implements AbstractFactory {
    public IPhone makePhone() {
        return new HuaWeiPhone();
    }

    public Computer makeComputer() {
        return new HuaWeiComputer();
    }
}

AppleFactory类:增加苹果Computer的制造(ConcreteFactory2)

public class AppleFactory implements AbstractFactory {
    public IPhone makePhone() {
        return new ApplePhone();
    }

    public Computer makeComputer() {
        return new AppleComputer();
    }
}

AbstractFactoryDemo

public class AbstractFactoryDemo {
    public static void main(String[] args) {
        AbstractFactory huaWeiFactory = new HuaWeiFactory();
        AbstractFactory appleFactory = new AppleFactory();
        huaWeiFactory.makePhone();
        huaWeiFactory.makeComputer();
        appleFactory.makePhone();
        appleFactory.makeComputer();
    }
}

输出

make huawei phone!
make huawei computer!
make apple phone!
make apple computer!

优点:能够从多个产品族的多个产品中,简洁的获取想要的具体产品。解决了工厂模式中的不符合开闭原则的问题(增加新的产品时候,不修改工厂,而是增加工厂)。

缺点:产品族扩展比较困难,要增加一个系列的某一产品,要增加具体的产品类,还要增加对应的工厂类(或者修改对应产品族的工厂类)。

应用场景:

解决两个维度的组合产品的构造问题,取其中一个维度作为产品族,另外一个维度作为产品族中具体的多个产品。

区别

工厂方法模式:

一个抽象产品类,可以派生出多个具体产品类。

一个抽象工厂类,可以派生出多个具体工厂类。

每个具体工厂类只能创建一个具体产品类的实例。

抽象工厂模式:

多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。

一个抽象工厂类,可以派生出多个具体工厂类。

每个具体工厂类可以创建多个具体产品类的实例。

总结

工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。

工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。

如果大家对java架构相关感兴趣,可以关注下面公众号,会持续更新java基础面试题, netty, spring boot,spring cloud等系列文章,一系列干货随时送达, 超神之路从此展开, BTAJ不再是梦想!

架构殿堂

你可能感兴趣的:(java基础,Java面试,设计模式,java,设计模式)