Java设计模式·工厂模式(简单工厂+工厂方法+抽象工厂)

一、工厂模式概要

        在面向对象编程中,创建对象实例最常用的方式就是通过 new 操作符构造一个对象实例,但在某些情况下,new 操作符直接生成对象会存在一些问题。举例来说,对象的创建需要一系列的步骤:可能需要计算或取得对象的初始位置、选择生成哪个子对象实例、或在生成之前必须先生成一些辅助对象。 在这些情况,新对象的建立就是一个 “过程”,而不仅仅是一个操作,就像一部大机器中的一个齿轮传动。

        针对上面这种情况,我们如何轻松方便地构造对象实例,而不必关心构造对象示例的细节和复杂过程?解决方案就是使用一个工厂类来创建对象。

概述:在工厂模式中,用factory模式代替使用new创建对象,实现了创建者和调用者的分离,方便维护对象。

实现方式:是面向接口编程

主要遵循:开闭原则,对类可以扩展,但是不允许对类修改。

面向对象设计基本原则:

 

        什么是工厂模式

 工厂模式其目的是将创建对象的具体过程屏蔽隔离起来,从而达到更高的灵活性,工厂模式可以分为三类:

  • 简单工厂模式(Simple Factory)
  • 工厂方法模式(Factory Method)
  • 抽象工厂模式(Abstract Factory)

        这三种模式从上到下逐步抽象,并且更具一般性。《设计模式》一书中将工厂模式分为两类:工厂方法模式与抽象工厂模式。将简单工厂模式看为工厂方法模式的一种特例,两者归为一类。 我们先从以下案例对工厂模式做个初步的了解:

(1)在没有工厂的时代,如果客户需要一款宝马车,那么就需要客户去创建一款宝马车,然后拿来用。

(2)简单工厂模式:后来出现了工厂,用户不再需要去创建宝马车,由工厂进行创建,想要什么车,直接通过工厂创建就可以了。比如想要320i系列车,工厂就创建这个系列的车。

 简单工厂模式的核心是定义一个创建对象的接口,将对象的创建和本身的业务逻辑分离

(3)工厂方法模式:为了满足客户,宝马车种类越来越多,如汽油驱动、电力驱动等等,一个工厂无法创建所有的汽车种类,于是又单独分出来多个具体的工厂,每个具体工厂创建一种车型,即具体工厂类只能创建一个或一种具体产品。但是宝马工厂还是个抽象,你需要指定某个具体的工厂才能生产车出来。

工厂方法模式将工厂抽象化,并定义一个创建对象的接口。每增加新产品,只需增加该产品以及对应的具体实现工厂类,由具体工厂类决定要实例化的产品是哪个,将对象的创建与实例化延迟到子类,这样工厂的设计就符合“开闭原则”了,扩展时不必去修改原来的代码。

(4)抽象工厂模式:随着各个品牌相继推出了自己的各个驱动类型的车型,客户的选择也越来越多,此时不仅是宝马,崛起了众如吉利、比亚迪等品牌

抽象工厂模式主要用于创建相关对象的家族。当一个产品族中需要被设计在一起工作时,通过抽象工厂模式,能够保证客户端始终只使用同一个产品族中的对象;并且通过隔离具体类的生成,使得客户端不需要明确指定具体生成类;所有的具体工厂都实现了抽象工厂中定义的公共接口,因此只需要改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。

二、简单工厂---工厂---抽象工厂的演变过程

1、简单工厂模式

应用简单工厂创建单个车型(电车,油车,混能车),用户选择车型即创建对应车型。

为了便于理解,可以看下列UML类图的结构

在创建车型时,电车,油车,混能车都会作为一个具体的车型出现,且同属于”车“这个抽象类,再搭建一个工厂类来根据用户输入的车型,创建对应的车型:

创建抽象接口Car

public interface Car {
    public void createCar();
}

 创建具体车型类并实现Car接口

public class Ecar implements Car{
    @Override
    public void createCar() {
        System.out.println("造出电车");
    }
}

public class Ocar implements Car{
    @Override
    public void createCar() {
        System.out.println("造出油车");
    }
}

 
public class Mcar implements Car{
    @Override
    public void createCar() {
        System.out.println("造出混能车");
    }
}


创建工厂类

public class CarFactory {
 
    public Car createCar(String choice) {
        Car car = null;
        switch (choice) {
            case "电车":
                car = new Ecar();
                break;
            case "油车":
                car = new Ocar();
                break;
            case "混能车":
                car = new Mcar();
                break;
        }
        return car;
    }
}


 测试

public class Test1 {
    public static void main(String[] args) {
        CarFactory carFactory = new CarFactory();
        Car car = carFactory.createCar("油车");
        car.createCar();
    }
}

 优点:

简单工厂模式提供专门的工厂类用于创建对象,实现了对象创建和使用的职责分离,客户端不需知道所创建的具体产品类的类名以及创建过程,只需知道具体产品类所对应的参数即可,通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。

缺点:

增加新的具体产品需要修改原来工厂类的判断逻辑代码。违背开闭原则

在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展维护,并且工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。

2、工厂方法模式

为了解决简单工厂的违反开闭原则,就出现了工厂方法模式,每一个具体车型类,有一个自己的创建自己对象的工厂,从而避免违反开闭原则。并提高代码结构稳定性。

为了便于理解,可以看下列UML类图的结构

修改CarFactory类改为接口

public interface CarFactory {
    public Car createCar();
}

 创建具体型类的工厂

public class EcarFactory implements CarFactory{
    @Override
    public Car createCar() {
        return new Ecar();    //电车
    }
}

public class OcarFactory implements CarFactory{
    @Override
    public Car createCar() {
        return new Ocar();    //油车
    }
}

public class ,carFactory implements CarFactory{
    @Override
    public Car createCar() {
        return new Mcar();    //混动
    }
}

测试

public class Test {
    public static void main(String[] args) {
        CarFactory carFactory = new EcarFactory();
        Car car = carFactory.createCar();
        car.createCar();
    }
}

优点:

用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程。

高层模块只需要知道产品的抽象类,无须关心其他实现类,满足迪米特法则、依赖倒置原则和里氏替换原则。不会修改原有的代码,不会违法开闭原则。

缺点: 

创建新产品需要创建相应的工厂类和具体类,代码结构相较于简单工厂模式更加复杂一点。

3、抽象工厂模式

  在工厂方法模式中,我们使用一个工厂创建一个产品,一个具体工厂对应一个具体产品,但有时候我们需要一个工厂能够提供多个产品对象,而不是单一的对象,这个时候我们就需要使用抽象工厂模式。

可以看到,上面只是对单个品牌的车企做到工厂创建实体,在多品牌的情况下就需要运用到抽象工厂了:

为了便于理解,可以看下列UML类图的结构

创建电车,油车,混能车的抽象接口

public interface Ecar {
    public void createCar();
}
 
 
public interface Mcar {
    public void createCar();
}
 
public interface Ocar{
    public void createCar();
}

创建具体品牌车型的具体类(其他车型以此类推)

public class BenzEcat implements Ecar {
    @Override
    public void createCar() {
        System.out.println("奔驰电车");
    }
}
 
public class BmwEcat implements Ecar {
    @Override
    public void createCar() {
        System.out.println("宝马电车");
    }
}
 
public class BydEcat implements Ecar {
    public void createCar(){
        System.out.println("比亚迪电车");
    }
}

创建抽象车型工厂接口

public interface CatFactory {
    public Ecat createEcar();
    public Ocat createOcar();
    public Mcat createMcar();
}

创建具体品牌的工厂实现接口工厂CarFactory(其他品牌以此类推)

public class BmwCarFactory implements CarFactory{
    @Override
    public Ecat createEcar() {
        return new BmwEcar();
    }
 
    @Override
    public Ocat createOcar() {
        return new BmwOcar();
    }
 
    @Override
    public Mcat createMcar() {
        return new BmwMcar();
    }
}

 测试

public class test {
    public static void main(String[] args) {
        //抽象工厂测试
        CarFactory carFactory = new BmwCarFactory();
        Ocar ocar = carFactory.createOcat();
        ocar.createCat();
    }
}

4、抽象工厂模式---简单抽象工厂模式

为了便于理解,可以看下列UML类图的结构

将工厂类替换为:

public class SimpleAbstractCatFactory {
    public Ecar createEcar(String brand) {
        Ecar ecar = null;
        switch (brand) {
            case "比亚迪":
                ecar = new BydEcar();
                break;
            case "宝马":
                ecar = new BmwEcar();
                break;
            case "奔驰":
                ecar = new BenzEcar();
                break;
        }
        return ecar;
    }
 
    public Ocar createOcar(String brand) {
        Ocar ocar = null;
        switch (brand) {
            case "比亚迪":
                ocar = new BydOcar();
                break;
            case "宝马":
                ocar = new BmwOcar();
                break;
            case "奔驰":
                ocar = new BenzOcar();
                break;
        }
        return ocar;
    }
 
    public Mcar createMcar(String brand) {
        Mcar mcar = null;
        switch (brand) {
            case "比亚迪":
                mcat = new BydMcar();
                break;
            case "宝马":
                mcat = new BmwMcar();
                break;
            case "奔驰":
                mcat = new BenzMcar();
                break;
        }
        return mcar;
    }
}

工厂模式小结

工厂方法模式与抽象工厂模式的区别在于:

(1)工厂方法只有一个抽象产品类和一个抽象工厂类,但可以派生出多个具体产品类和具体工厂类,每个具体工厂类只能创建一个具体产品类的实例。

(2)抽象工厂模式拥有多个抽象产品类(产品族)和一个抽象工厂类,每个抽象产品类可以派生出多个具体产品类;抽象工厂类也可以派生出多个具体工厂类,同时每个具体工厂类可以创建多个具体产品类的实例

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值