设计模式之工厂模式

127 阅读4分钟

一、关于工厂

说到工厂,我们都知道工厂就是生产东西的地方。对于我们用户来说,工厂只要能生产出来我们需要的东西就可以了,至于工厂生产产品的过程我们无需关心。同理,工厂模式关注点也是这样的,不过工厂模式也由不同的类型,每种类型也各有优劣。

二、简单工厂

2.1 场景

现在有个生产电脑的工厂,这个工厂里可以生产不同的电脑,其中电脑需要达到一定的标准,我们才认为是合格的产品。

2.2 代码转换

基于上面的描述,我们需要定义一个接口来表示该产品的标准。

/**
 * 这里相当于电脑的各种标准和数据
 */
public interface Computer {
    // 获取电脑的品牌
    String getBrand();
}

基于以上的标准,我们来定义三种不同品牌的电脑。

public class Apple implements Computer {
    @Override
    public String getBrand() {
        return "苹果";
    }
}

public class HuaWei implements Computer {
    @Override
    public String getBrand() {
        return "华为";
    }
}

public class Lenovo implements Computer {
    @Override
    public String getBrand() {
        return "联想";
    }
}

2.3 创建工厂

现在有个工厂,这个工厂可以用户要求生产以上三种不同品牌的电脑。

public class SimpleFactory {
    public Computer getComputer(String brand) {
        if ("Lenove".equalsIgnoreCase(brand)) {
            return new Lenovo();
        } else if ("HuaWei".equalsIgnoreCase(brand)) {
            return new HuaWei();
        } else if ("Apple".equalsIgnoreCase(brand)) {
            return new Apple();
        } else {
            System.out.println("我们无法生产该品牌的电脑...");
            return null;
        }
    }
}

2.4 用户验证

现在,我们想要一台华为的电脑。

public class SimpleFactoryTest {
    public static void main(String[] args) {
        SimpleFactory factory = new SimpleFactory();
        Computer computer = factory.getComputer("huawei");
        System.out.println("我们从工厂获取的电脑为:" + computer.getBrand());
    }
}

2.5 问题

通过上面的代码过程,可以满足我们的需求。不过,我们也可以发现,其存在一些问题。

  • 生活中有没有一个工厂可以生产所有品牌的电脑呢?
  • 在工厂代码中,若存在大量品牌的电脑,就需要写大量if else,这样好吗?

三、工厂方法

通过上面简单工厂的介绍,我们了解了其存在的问题,那么有没有其他的方式去避免呢?

3.1 分析

在简单工厂中,我们关注的点其实还是以电脑为主。这里,我们转换视角,将重点放到工厂上,既然电脑是有标准的,同理,工厂也是有标准的,电脑工厂我们要求只能生产电脑。

3.2 创建工厂

基于以上,我们定义工厂的标准,即标准即为接口。

/**
 * 工厂方法
 * 电脑工厂标准
 */
public interface ComputerFactory {
    Computer getComputer();
}

3.3 实现工厂

实际情况是,不同的品牌都是有自己的工厂的,例如:苹果工厂、联想工厂、华为工厂。可是不管是哪种类型的电脑工厂,都必须实现电脑工厂标准,即可以生产电脑。

public class AppleFactory implements ComputerFactory {
    @Override
    public Computer getComputer() {
        return new Apple();
    }
}

public class HuaWeiFactory implements ComputerFactory {
    @Override
    public Computer getComputer() {
        return new HuaWei();

    }
}

public class LenovoFactory implements ComputerFactory {
    @Override
    public Computer getComputer() {
        return new Lenovo();
    }
}

3.4 验证

现在用户想要一台电脑。

public class FactoryMethodTest {
    public static void main(String[] args) {
        ComputerFactory factory = new AppleFactory();
        System.out.println(factory.getComputer());

        factory = new LenovoFactory();
        System.out.println(factory.getComputer());
    }
}

感觉好了一点,与实际生活更加贴合了。当出现了一个新的品牌,我们只需按照标准,创建工厂,然后生产即可。

3.5 问题

我们再次转换视角,我们关注点从电脑、工厂转到用户本身来看。在验证环节,我们看到,当我们想要某个品牌的电脑时,我们需要直接找到对应的工厂,这样符合实际情况吗?

  • 我们买电脑需要直接到工厂去吗?

四、抽象工厂

由于以上两种工厂方式多少都存在一些问题,更加实际的情况是:当我们需要一台电脑时,我们直接到电脑商城去,说我需要一台华为电脑,至于这台电脑背后工厂生产我们不关心,甚至于,是不是华为工厂生产的我们也不关心【即代工】。

4.1 创建工厂

public abstract class AbstractFactory {
    abstract Computer getComputer();
}

4.2 实现工厂

public class AppleFactory extends AbstractFactory {
    @Override
    Computer getComputer() {
        return new Apple();
    }
}
public class HuaWeiFactory extends AbstractFactory {
    @Override
    Computer getComputer() {
        return new HuaWei();
    }
}
public class LenovoFactory extends AbstractFactory {
    @Override
    Computer getComputer() {
        return new Lenovo();
    }
}

4.3 商场

public class ComputerMarket {

    public Computer getComputer(String brand) {
        if ("Lenove".equalsIgnoreCase(brand)) {
            return new LenovoFactory().getComputer();
        } else if ("HuaWei".equalsIgnoreCase(brand)) {
            return new HuaWeiFactory().getComputer();
        } else if ("Apple".equalsIgnoreCase(brand)) {
            return new AppleFactory().getComputer();
        } else {
            System.out.println("我们无法找到该品牌的电脑...");
            return null;
        }
    }
}

4.4 验证

public class AbstractFactoryTest {
    public static void main(String[] args) {
        ComputerMarket market = new ComputerMarket();
        Computer computer = market.getComputer("huawei");
        System.out.println(computer);
    }
}

这样,我们只需要和商城反映,我们需要某个品牌的电脑,由商场去和工厂打交道拿到对应电脑给我们。后续,当有新的品牌出现时,其他工厂无需变化,只要创建对应的工厂,之后,将该品牌添加到商场即可。

4.5 问题

前面都没问题了,当品牌太多时,商场还不是需要维护大量的品牌,即大量的if else,这样商场类这么定义合适吗?