美文网首页
设计模式-工厂模式

设计模式-工厂模式

作者: 奔向学霸的路上 | 来源:发表于2020-04-21 12:09 被阅读0次

在Java语言中,我们通常由以下几种创建对象的方式:
(1)使用new关键字直接创建对象
(2)通过反射机制创建对象
(3)通过clone()方法创建对象
(4)通过工厂类创建对象

接下来我们学习使用工厂类创建对象

工厂模式介绍

工厂模式的定义

“Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.”(在基类中定义创建对象的一个接口,让子类决定实例化哪个类。工厂方法让一个类的实例化延迟到子类中进行。)

工厂模式的分类

  1. 简单工厂模式:允许接口创建对象,但不会暴露对象的创建逻辑。
  2. 工厂方法模式:允许接口创建对象,但使用哪个类来创建对象,则时交由子类决定的。
  3. 抽象工厂模式:抽象工厂时一个能够创建一系列相关的对象而无需指定/公开其具体类的接口。

在开源框架中的使用

  1. Spring中同通过getBean("xxx")获取Bean;
  2. Java消息服务JMS中

使用工厂模式的优点

  1. 解耦:把对象的创建和使用分开
  2. 降低代码重复:如果创建某个对象的过程很复杂,需要一定的代码量,而且很多地方都要用到,那么就会由很多的重复代码
  3. 降低维护成本:由于创建过程都由工厂统一管理,所有发生业务逻辑变化,不需要找到所有需要创建某个对象的地方去逐个修正,只需要在工厂里修改即可,降低维护成本。

简单工厂模式

工厂可以帮助开发人员创建不同类型的对象,而不是直接对对象实例化。

介绍

严格来讲,简单工厂模式并不算23种常见的设计模式之一,它只算工厂模式的一个特殊实现。简单工厂模式在实际中用的比其他两种要少得多。

它违背了“开闭原则”(可以通过反射来避免),因为每次添加一个功能,都需要在switch-case或者if-else语句中去修改代码,添加分支条件。

适用场景

  1. 需要创建的对象较少。
  2. 客户端不关心对象的创建过程。

简单工厂模式角色分配

  1. 工厂角色:负责实现创建所有实例的内部逻辑,工厂类可以被外界直接调用,创建所需的产品对象。
  2. 抽象产品角色:所需创建对象的父类
  3. 具体产品角色:某个具体类的实例

简单工厂实例

//创建Shape接口
public interface Shape {
    void draw();
}
//圆形
public class Circle implements Shape {
    public Circle() {
        System.out.println("Circle");
    }
    @Override
    public void draw() {
        System.out.println("Draw Circle");
    }
}
//长方形
public class Rectangle implements Shape {
    public Rectangle() {
        System.out.println("Rectangle");
    }
    @Override
    public void draw() {
        System.out.println("Draw Rectangle");
    }
}
//正方形
public class Square implements Shape {
    public Square() {
        System.out.println("Square");
    }

    @Override
    public void draw() {
        System.out.println("Draw Square");
    }
}
//创建工厂类
public class ShapeFactory {

    // 使用 getShape 方法获取形状类型的对象
    public static Shape getShape(String shapeType) {
        if (shapeType == null) {
            return null;
        }
        if (shapeType.equalsIgnoreCase("CIRCLE")) {
            return new Circle();
        } else if (shapeType.equalsIgnoreCase("RECTANGLE")) {
            return new Rectangle();
        } else if (shapeType.equalsIgnoreCase("SQUARE")) {
            return new Square();
        }
        return null;
    }
}
//测试方法
public class Test {

    public static void main(String[] args) {

        // 获取 Circle 的对象,并调用它的 draw 方法
        Shape circle = ShapeFactory.getShape("CIRCLE");
        circle.draw();

        // 获取 Rectangle 的对象,并调用它的 draw 方法
        Shape rectangle = ShapeFactory.getShape("RECTANGLE");
        rectangle.draw();

        // 获取 Square 的对象,并调用它的 draw 方法
        Shape square = ShapeFactory.getShape("SQUARE");
        square.draw();
    }
}

如果我们新增产品类的话,就需要修改工厂类的getShape()方法,这显然不符合开闭原则

使用反射来避免上述问题

public class ShapeFactory2 {
    public static Object getClass(Class<? extends Shape> clazz) {
        Object obj = null;
        try {
            obj = Class.forName(clazz.getName()).newInstance();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return obj;
    }
}

测试方法:

Circle circle = (Circle) ShapeFactory2.getClass(com.example.leanspringboot.designpattern.business.impl.Circle.class);
        circle.draw();

这种方式虽然符合了开闭原则,但是每一次传入的都是全部路径,比较麻烦。改善方式可以通过 反射+配置文件的形式来改善,这种方式使用的也是比较多的。

工厂方法模式

介绍

这是工厂模式使用最多的一种,工厂方法模式是简单工厂的进一步深化,在工厂方法模式中,我们不再提供一个统一的工厂类来创建所有的对象,而是针对不同对象提供不同的工厂。也就是说每个对象都有一个与之对应的工厂。

适用创景

  1. 一个类不知道它所需要的对象的类:在工厂方法模式中,客户端不需要指定具体产品类的类名,只需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体的产品对象由具体工厂类创建;客户端需要知道创建具体产品的工厂类。
  2. 一个类通过其子类来指定创建哪个对象:在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,利用面向对象的多态性和里氏代换原则,将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无需关心时哪一个工厂子类创建产品子类,需要时再动态指定,可将具体工厂类的类名存储在配置文件或者数据库中。

工厂方法模式角色分配

  1. 抽象工厂角色:是工厂方法模式的核心,与应用程序无关,任何在模式中创建的对象的工厂类必须实现这个接口。
  2. 具体工厂角色:这是实现抽象工厂接口的具体工厂类,包含于应用程序密切相关的逻辑,并且受到应用程序调用以创建某一种产品对象。
  3. 抽象产品角色:工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。
  4. 具体产品角色:这个角色实现了抽象产品角色所定义的接口。某具体产品有专门的集体工厂创建,它们一一对应。

工厂方法模式实例

1. 增加一个工厂接口

public interface Factory {
    Shape getShape();
}

2.增加一组工厂类

public class CircleFactory implements Factory {
    @Override
    public Shape getShape() {
        return new Circle();
    }
}

public class RectangleFactory implements Factory {
    @Override
    public Shape getShape() {
        return new Rectangle();
    }
}

public class SquareFactory implements Factory {
    @Override
    public Shape getShape() {
        return new Square();
    }
}

测试

        Factory circleFactory = new CircleFactory();
        Shape circle = circleFactory.getShape();
        circle.draw();

抽象工厂模式

介绍

在工厂方法模式中,其实我们有一个潜意识,那就是我们生成的都是同一类产品。抽象工厂就是抽象工厂方法的进一步深化,在这个模式中的工厂类不单单可以创建一种产品,而是可以创建一组产品。

适用场景

  1. 和工厂方法一样客户的不需要知道它所创建的对象的类
  2. 需要一组对象共同完成某种功能时,并且可能存在多组对象完成不同功能的情况。(同属于同一个产品族的产品)
  3. 系统结构稳定,不会频繁的增加对象。(因为一旦增加就需要修改原有代码,不符合开闭原则)

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

  1. 抽象工厂(AbstractFactory)角色 :是工厂方法模式的核心,与应用程序无关。任何在模式中创建的对象的工厂类必须实现这个接口。
  2. 具体工厂类(ConreteFactory)角色 :这是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建某一种产品对象。
  3. 抽象产品(Abstract Product)角色 :工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。
  4. 具体产品(Concrete Product)角色 :抽象工厂模式所创建的任何产品对象都是某一个具体产品类的实例。在抽象工厂中创建的产品属于同一产品族,这不同于工厂模式中的工厂只创建单一产品,我后面也会详解介绍到。

抽象工厂的工厂和工厂方法总的工厂有什么区别

抽象工厂是生产一整套有产品的(至少要生产两个产品),这些产品必须相互是有关系或有依赖的,而工厂方法中的工厂是生产单一产品的工厂。

抽象工厂模式实例

不知道大家玩过穿越火线或者吃鸡这类游戏了吗,游戏中存在各种枪。我们假设现在存在AK、M4A1两类枪,每一种枪对应一种子弹。我们现在这样考虑生产AK的工厂可以顺便生产AK使用的子弹,生产M4A1的工厂可以顺便生产M4A1使用的子弹。(AK工厂生产AK系列产品包括子弹啊,AK枪的类型啊这些,M4A1工厂同理)

1. 创建相关接口

public interface Gun {
    void shooting();
}

子弹

public interface Bullet {
    void load();
}

2. 创建接口对应实现类

AK类

public class AK implements Gun{

    @Override
    public void shooting() {
        System.out.println("shooting with AK");

    }

}

M4A1类

public class M4A1 implements Gun {

    @Override
    public void shooting() {
        System.out.println("shooting with M4A1");
    }
}

AK子弹类

public class AK_Bullet implements Bullet {

    @Override
    public void load() {
        System.out.println("Load bullets with AK");
    }
}

M4A1子弹类

public class M4A1
_Bullet implements Bullet {

    @Override
    public void load() {
        System.out.println("Load bullets with M4A1");
    }

}

3. 创建工厂接口

public interface Factory {
    public Gun produceGun();
    public Bullet produceBullet();
}

4. 创建具体工厂
生产AK和AK子弹的工厂

public class AK_Factory implements Factory{

    @Override
    public Gun produceGun() {
        return new AK();
    }

    @Override
    public Bullet produceBullet() {
        return new AK_Bullet();
    }

}

生产M4A1和M4A1子弹的工厂

public class M4A1_Factory implements Factory{

    @Override
    public Gun produceGun() {
        return new M4A1();
    }

    @Override
    public Bullet produceBullet() {
        return new M4A1_Bullet();
    }

}

测试

public class Test {

    public static void main(String[] args) {  

     Factory factory;
     Gun gun;
     Bullet bullet;

     factory =new AK_Factory();
     bullet=factory.produceBullet();
     bullet.load();
     gun=factory.produceGun();
     gun.shooting(); 

    }

}

原文链接:http://www.imooc.com/article/31360

相关文章

  • 设计模式四、抽象工厂模式

    系列传送门设计模式一、单例模式设计模式二、简单工厂模式设计模式三、工厂模式设计模式四、抽象工厂模式 抽象工厂模式 ...

  • 工厂模式

    java设计模式-工厂模式 工厂模式: 工厂模式是java设计模式里最常用的设计模式之一。 工厂模式属于创建型模式...

  • 设计模式之工厂模式

    设计模式之工厂模式 标签(空格分隔): 设计模式 工厂模式 设计模式的感念 设计模式的应用 工厂设计模式的产生 工...

  • 设计模式三、工厂模式

    系列传送门设计模式一、单例模式设计模式二、简单工厂模式设计模式三、工厂模式设计模式四、抽象工厂模式 工厂模式 在一...

  • 设计模式一、单例模式

    系列传送门设计模式一、单例模式设计模式二、简单工厂模式设计模式三、工厂模式设计模式四、抽象工厂模式 简单单例(推荐...

  • 单件设计模式

    一、定义 设计模式 设计模式就是一种更好的编写代码方案。 常见设计模式 工厂设计模式、抽象工厂设计模式、抽象工厂设...

  • iOS设计模式(三)之抽象工厂模式

    设计模式系列传送门 iOS设计模式(一)之简单工厂模式iOS设计模式(二)之工厂模式iOS设计模式(三)之抽象工厂...

  • iOS设计模式(一)之简单工厂模式

    设计模式系列传送门 iOS设计模式(一)之简单工厂模式iOS设计模式(二)之工厂模式iOS设计模式(三)之抽象工厂...

  • iOS设计模式(二)之工厂模式

    设计模式系列传送门 iOS设计模式(一)之简单工厂模式iOS设计模式(二)之工厂模式iOS设计模式(三)之抽象工厂...

  • 常用设计模式

    设计模式 工厂模式 工厂模式思路上分:简单工厂模式,工厂模式, 抽象工厂模式// 抽象工厂模式可以代替工厂模式,做...

网友评论

      本文标题:设计模式-工厂模式

      本文链接:https://www.haomeiwen.com/subject/ezuyihtx.html