设计模式(二)-----工厂模式(Factory Pattern)


工厂模式是我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式。因为工厂模式就相当于创建实例对象的new,我们经常要根据类Class生成实例对象,如A a=new A() 工厂模式也是用来创建实例对象的,所以以后new时就要多个心眼,是否可以考虑使用工厂模式,虽然这样做,可能多做一些工作,但会给你系统带来更大的可扩展性和尽量少的修改量。

涉及到的完整代码

什么是工厂模式

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

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

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

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

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

(3)工厂方法模式:为了满足客户,奔驰车系列越来越多,如奔驰s、奔驰e等等系列,一个工厂无法创建所有的奔驰系列,于是又单独分出来多个具体的工厂,每个具体工厂创建一种系列,即具体工厂类只能创建一个具体产品。但是奔驰工厂还是个抽象,你需要指定某个具体的工厂才能生产车出来。

(4)抽象工厂模式:随着客户要求越来越高,奔驰车必须配置空调,于是这个工厂开始生产奔驰车和需要的空调。最终是客户只要对奔驰的销售员说:我要奔驰s空调车,销售员就直接给他奔驰s空调车了。而不用自己去创建奔驰s空调车。

简单工厂模式

简单工厂模式的核心是定义一个创建对象的接口,将对象的创建和本身的业务逻辑分离,降低系统的耦合度,使得两个修改起来相对容易些,当以后实现改变时,只需要修改工厂类即可

简单工厂模式中的角色分工:

  • 工厂类:负责创建用户所需的产品对象。
  • 产品接口:是简单工厂创建的所有对象的父类,描述了具体产品类的所有公共属性。
  • 具体的产品类:被简单工厂模式创建的对象,是产品接口的不同具体实现类。

产品类

public interface BenzCreate {
    void create();
}

public class BenzE implements BenzCreate {
    @Override
    public void create() {
        System.out.println("建造奔驰E");
    }
}

public class BenzS implements BenzCreate {
    @Override
    public void create() {
        System.out.println("建造奔驰S");
    }
}

工厂类

public class BenzFactory {
    public static BenzCreate benzCreate(String type) {
        switch (type) {
            case "S":
                return new BenzS();
            case "E":
                return new BenzE();
            default:
                break;
        }
        return null;
    }
}

用户类

public class Test {
    public static void main(String[] args) {
        //建造奔驰S
        BenzCreate S = BenzFactory.benzCreate("S");
        S.create();
        //建造奔驰E
        BenzCreate E = BenzFactory.benzCreate("E");
        E.create();

    }
}

简单工厂模式的优点:

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

简单工厂模式的缺点:
但缺点在于不符合“开闭原则”,每次添加新产品就需要修改工厂类。在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展维护,并且工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。

   为了解决简单工厂模式的问题,出现了工厂方法模式。

工厂方法模式

工厂方法模式将工厂抽象化,并定义一个创建对象的接口。每增加新产品,只需增加该产品以及对应的具体实现工厂类,由具体工厂类决定要实例化的产品是哪个,将对象的创建与实例化延迟到子类,这样工厂的设计就符合“开闭原则”了,扩展时不必去修改原来的代码。在使用时,用于只需知道产品对应的具体工厂,关注具体的创建过程,甚至不需要知道具体产品类的类名,当我们选择哪个具体工厂时,就已经决定了实际创建的产品是哪个了。

但缺点在于,每增加一个产品都需要增加一个具体产品类和实现工厂类,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。

工厂方法模式中的角色分工:

  • 工厂接口:定义了生产产品的方法,但没有具体的实现该方法,方法的实现交给具体的工厂子类实现。
  • 具体的工厂子类:实现了工厂接口中定义的生产产品的方法,负责生产具体的产品对象。
  • 产品接口:具体产品类的父类,描述了具体产品的所有公共属性。
  • 具体的产品类:产品接口的具体实现,是被工厂创建的对象。

产品类:

public interface BenzCreate {
    void create();
}

public class BenzE implements BenzCreate {
    @Override
    public void create() {
        System.out.println("建造奔驰E");
    }
}

public class BenzS implements BenzCreate {
    @Override
    public void create() {
        System.out.println("建造奔驰S");
    }
}

工厂类:

public interface BenzFactory {
      BenzCreate benzCreate();
}

public class BenzEFactory implements BenzFactory {
    @Override
    public BenzCreate benzCreate() {
        return new BenzE();
    }
}

public class BenzSFactory implements BenzFactory {
    @Override
    public BenzCreate benzCreate() {
        return new BenzS();
    }
}

客户类:

public class Test {
    public static void main(String[] args) {
        BenzSFactory benzSFactory = new BenzSFactory();
        benzSFactory.benzCreate().create();

        BenzEFactory benzEFactory = new BenzEFactory();
        benzEFactory.benzCreate().create();
    }
}

工厂方法模式需要创建对应的车型工厂实例,才能获取到对应车型对象。可能会有小伙伴觉得这不是脱了裤子放屁——多此一举吗?明明可以直接new 一个我们需要的车型对象。其实是因为这个例子比较简单,通常工厂方法模式用于对象的创建逻辑比较复杂,代码繁琐的场景。

​ 如JDBC常用的PreparedStatement对象,还记得创建PreparedStatemenet对象的步骤吗?

​ 加载驱动–>连接数据库–>获取Connection对象–>获取PreparedStatement对象。

运用工厂方法模式就可以将这些步骤封装起来,简化程序代码。

工厂方法模式的优点:
​ 方便产品扩展,工厂类的职责清晰,结构简单。例如我如果想在项目中添加一个linux课程,只需要在项目中添加一个LinuxCourse类,和LinuxCourseFactory类即可,不用对之前的代码做任何修改。

工厂方法模式的缺点:
​ 每种产品类都对应着一种工厂类,当商品的种类增多时,维护起来有一定难度。

抽象工厂模式

工厂方法模式中只有一个抽象方法,要想获得不同类型的产品对象,就要创建不同的工厂子类对象,而抽象工厂则是让一个工厂负责创建多个不同类型的对象。

抽象工厂模式适用于:需要一组对象共同完成某种功能时,并且可能存在多组对象完成不同功能的情况。(同属于同一个产品族的产品);系统结构稳定,不会频繁的增加对象。

抽象工厂方法模式角色分工:

  • 工厂接口:定义了各种产品的生产方法,具体的方法实现交由工厂子类实现。
  • 工厂子类:实现工厂接口中定义的方法,负责生产某一类产品对象。
  • 产品接口:具体产品类的父类,描述了具体产品的所有公共属性。
  • 具体的产品类:产品接口的具体实现,是被工厂创建的对象。

产品类:

public interface Engine {
    void creat();
}
public class EngineE implements Engine{
    @Override
    public void creat() {
        System.out.println("生产奔驰E的发动机");
    }
}
public class EngineS implements Engine{
    @Override
    public void creat() {
        System.out.println("生产奔驰S的发动机");
    }
}

public interface Aircondition {
    void creat();
}
public class AirconditionE implements Aircondition {
    @Override
    public void creat() {
        System.out.println("生产奔驰E的空调");
    }
}
public class AirconditionS implements Aircondition{
    @Override
    public void creat() {
        System.out.println("生产奔驰S的空调");
    }
}

创建工厂类:

public interface BenzFactory {
    Engine createEngine();

    Aircondition createAircontion();
}
public class BenzEFactory implements BenzFactory {
        /**
     * 生产奔驰E的发动机
     * @return
     */
    @Override
    public Engine createEngine() {
        return new EngineE();
    }

    /**
     * 生产奔驰E的空调
     * @return
     */
    @Override
    public Aircondition createAircontion() {
        return new AirconditionE();
    }
}
public class BenzSFactory implements BenzFactory {
    /**
     * 生产发动机
     *
     * @return
     */
    @Override
    public Engine createEngine() {
        return new EngineS();
    }

    /**
     * 生产空调
     *
     * @return
     */
    @Override
    public Aircondition createAircontion() {
        return new AirconditionS();
    }
}

客户:

public class Test {
    public static void main(String[] args) {
        /**
         * 生产奔驰S的空调和发动机
         */
        BenzSFactory benzSFactory = new BenzSFactory();
        benzSFactory.createAircontion().creat();
        benzSFactory.createEngine().creat();
        /**
         * 生产奔驰E的空调和发动机
         */
        BenzEFactory benzEFactory = new BenzEFactory();
        benzEFactory.createAircontion().creat();
        benzEFactory.createEngine().creat();
    }
}

抽象工厂模式的优点:
一个工厂类可以创建一个系类的多个对象,简化了获取产品对象的复杂度 。
可以保证同一工厂生成的产品相互匹配,可以避免客户端和具体产品代码的耦合。
横向扩展简单:如果要新增一个系列的产品,只需增加一个工厂子类即可,不用修改原先的代码。例如我想在项目中添加一门奔驰A型车,只需要新建类 并实现对应的接口即可,不用对之前的代码做任何修改。
抽象工厂模式的缺点:
​ 纵向扩展困难:如果要在一个产品系列中增加一个新的产品,就需要对工厂接口,及工厂子类的代码进行修改。例如:现在不仅要求生产空调和发动机,还要生产玻璃;这就需要在工厂接口Factory,以及他的所有子类中添加生产玻璃的方法,违背了开闭原则

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

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

参考:

https://blog.csdn.net/a745233700/article/details/120253639
https://blog.csdn.net/m0_52383454/article/details/127415930

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值