首页 > 技术文章 > 简单工厂模式、工厂方法模式、抽象工厂模式

fanglongxiang 2020-06-29 23:07 原文

前言

简单工厂模式、工厂方法模式、抽象工厂模式,关联比较大 因此这里放在一起总结下。方便比较,容易理解和区分。

这3种模式也都是一种创建型模式(创建型模式提供了创建对象的机制,能够提升已有代码的灵活性和可复用性。)

先做个简单比较,有个大致了解,下面再通过例子具体说明

简单工厂模式 工厂方法模式 抽象工厂模式
违背开闭原则,不属于GoF的23种设计模式 属于 属于
只有三部分:产品接口,产品实现,工厂实现 四要素:产品接口,产品实现,工厂接口,工厂实现 具有工厂方法模式同样的四要素
单一产品 单一产品 多种层次结构的一系列产品
优点:屏蔽产品的具体实现,调用者只关心产品的接口 同左 同左
优点:产品实例化被封装,依赖工厂生成实例 同左 同左
优点:降低耦合,避免了调用者与产品之间的耦合 同左 同左
优点:扩展性高 同左 同左
不足:引入新的子类,使代码变复杂 同左 同左

简单工厂模式(Simple Factory)

概述

简单工厂模式,是由一个工厂决定创建哪一类产品的实例。

实现:demo

下面demo是,通过工厂类PhoneFactory获取Phone对象,通过参数type实例化不同的Phone对象。

产品接口:可以是抽象类也可以是接口,这里使用了抽象类

public abstract class Phone {
    void myBrand() {}
}

产品实现:两个产品苹果手机、华为手机

public class ApplePhone extends Phone {
    @Override
    public void myBrand() {
        System.out.println("苹果:iPhoneX");
    }
}

public class HuaWeiPhone extends Phone {
    @Override
    public void myBrand() {
        System.out.println("华为:P40");
    }
}

工厂类:比如富士康,同时代工生产 华为和苹果手机。

public class PhoneFactory {
    public static final int NO_PHONE = -1;
    public static final int HUAWEI = 1;
    public static final int APPLE = 2;
	
    public Phone getPhone(int type) {
        Phone phone = null;
        switch (type) {
            case HUAWEI:
            	phone = new HuaWeiPhone();
                break;
            case APPLE:
            	phone = new ApplePhone();
                break;
            case NO_PHONE:
            default:
                break;
        }
        return phone;
    }
}

调用demo:使用工厂类,通过参数创建和获取不同的产品实例。

public class SimplyFactoryTest {
    public static void main(String[] args) {
        PhoneFactory phoneFactory = new PhoneFactory();
        Phone huawei = phoneFactory.getPhone(PhoneFactory.HUAWEI);
        huawei.myBrand();
        
        Phone apple = phoneFactory.getPhone(PhoneFactory.APPLE);
        apple.myBrand();
    }
}

打印的信息如下:

华为:P40
苹果:iPhoneX

总结

简单工厂模式 违背了开闭原则,因此不属于GoF里的23种设计模式。他可以看作工厂模式的简化,没有工厂的接口。
开闭原则简单的说就是对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码。这里的不符合是因为:假如新增一个产品,则需要修改工厂类的条件。

工厂方法模式(Factory Method)

概述

工厂方法模式,可以看作简单工厂模式的演进。解决了简单工厂存在的问题:新增一个产品 需要修改工厂类条件。
它定义一个工厂接口(一个java接口或抽象类),让其子类自己决定实例化对象的类型,使其创建过程(由上面的工厂类)延迟到子类进行。

工厂方法模式核心结构有四个角色,分别是工厂接口;工厂实现;产品接口;产品实现。(简单工厂模式只有3个,没有工厂接口)。

实现:demo

产品接口和产品实现同简单工厂模式一样(即上面的Phone、ApplePhone 、HuaWeiPhone类),这里不再重复列出。

工厂接口(抽象工厂):

public interface IFactory {
    Phone productPhone();
}

工厂实现:华为工厂生产华为手机、苹果工厂生产苹果手机。

public class HuaWeiFactory implements IFactory {
    @Override
    public Phone productPhone() {
        return new HuaWei();
    }
}

public class AppleFactory implements IFactory {
    @Override
    public Phone productPhone() {
        return new Apple();
    }
}

调用demo:

public class FactoryMethodTest {
    public static void main(String[] args) {
        IFactory huaWeiFactory = new HuaWeiFactory();
        huaWeiFactory.productPhone().myBrand();
        IFactory appleFactory = new AppleFactory();
        appleFactory.productPhone().myBrand();
    }
}

结果:

华为:P40
苹果:iPhoneX

总结

当新增一个产品,如小米手机:我们只需新增一个XiaoMiPhone(继承Phone),一个XiaoMiFactory(实现IFactory)即可。
这样不会对原有代码有任何影响,但每增加一个产品,就需要增加一个产品实现、一个工厂实现,增加了代码量。

抽象工厂模式(Abstract Factory)

概述

抽象工厂模式,是针对多个产品(也是一系列的产品)。它定义了一个接口用于创建相关或有依赖关系的产品簇,而无需明确指定产品类。
比如,将factory理解成公司 即是华为公司、苹果公司。他们都设计生产手机和电脑等一系列产品。 你从华为公司,只会拿到华为的手机和电脑等、不会拿到苹果的产品。

实现:demo

基于上面工厂方法模式(已有的手机产品及工厂,Phone、ApplePhone 、HuaWeiPhone、HuaWeiFactory、AppleFactory类)

产品接口:新产品电脑

public interface IComputer {
    void computerName();
}

产品实现:苹果电脑、华为电脑

public class AppleComputer implements IComputer {
    @Override
    public void computerName() {
        System.out.println("苹果:MacBook Pro");
    }
}

public class HuaWeiComputer implements IComputer {
    @Override
    public void computerName() {
        System.out.println("华为:MateBook X Pro");
    }
}

抽象工厂:声明生产一系列抽象产品的方法

public interface IFactory {
    Phone productPhone();
    IComputer productComputer();
}

工厂实现:一个公司生产一系列产品,苹果公司设计生产苹果手机、苹果电脑;华为公司设计生产华为手机、华为电脑。

public class AppleFactory implements IFactory {
    @Override
    public Phone productPhone() {
        return new ApplePhone();
    }
    
    @Override
    public IComputer productComputer() {
        return new AppleComputer();
    }
}

public class HuaWeiFactory implements IFactory {
    @Override
    public Phone productPhone() {
        return new HuaWeiPhone();
    }
    
    @Override
    public IComputer productComputer() {
        return new HuaWeiComputer();
    }
}

调用demo:

public class AbstractFactoryTest {
    public static void main(String[] args) {
        IFactory huaWeiFactory = new HuaWeiFactory();
        huaWeiFactory.productPhone().myBrand();
        huaWeiFactory.productComputer().computerName();
        IFactory appleFactory = new AppleFactory();
        appleFactory.productPhone().myBrand();	
        appleFactory.productComputer().computerName();
    }
}

打印结果:

华为:P40
华为:MateBook X Pro
苹果:iPhoneX
苹果:MacBook Pro

总结

同一系列产品容易添加,像工厂方法模式一样。如小米公司:我们只需再新增一个XiaoMiPhone(继承Phone),一个XiaoMiComputer(实现IComputer),一个XiaoMiFactory(实现IFactory)即可。
产品簇中增加个新产品很难,如再增加个手表(Watch),需要新增手表的产品接口和实现,这是抽象工厂和工厂实现都需要进行修改。

推荐阅读