工厂模式

2020-04-26 10:07:26 浏览数 (2)

包含了简单工厂模式(并不在23中模式之中)、工厂方法模式以及抽象工厂模式。

下面结合定义和应用实例以及代码来给出我对这三种模式的理解,设计模式只是思想,融会贯通才是重要的

首先来看最简单的。

简单工厂模式:

简单工厂模式并不是一种设计模式,并不在23种设计模式之中

定义:定义一个工厂类,根据传入的参数不同返回不同的实例,被创建的实例具有共同的父类或接口。

代码演示:

  创建一个可以绘制不同形状的绘图工具,可以绘制圆形,三角形,长方形这三种图形,每个图形都会有一个draw()方法用于绘图

未使用设计模式代码:

  定义一个接口或者抽象类,作为这三个图像的公共父类,并声明draw方法。

代码语言:javascript复制
//定义成抽象类也是可以的,只不过接口是更高一级的抽象,所以习惯定义成接口,而且接口支持多实现,方便后续扩展。
public interface Shape {
    void draw();
}

  下面就是编写具体的图形,每种图形都实现Shape 接口

圆形

代码语言:javascript复制
public class Circle implements Shape{

    @Override
    public void draw() {
        System.out.println("圆形");
    }
}

三角形

代码语言:javascript复制
public class Triangle implements Shape{

    @Override
    public void draw() {
        System.out.println("三角形");
    }
}

长方形

代码语言:javascript复制
public class Rectangle implements Shape{

    @Override
    public void draw() {
        System.out.println("长方形");
    }
}

客户端:

未使用简单工厂前(客户端想要创建 圆形,三角形这两个形状,需要依赖进来具体形状类 Circle,Triangle)

代码语言:javascript复制
public class SimpleFactoryTest {
    public static void main(String[] args) {
        Circle circle =new Circle();
        circle.draw();
        Triangle triangle=new Triangle();
        triangle.draw();
    }
}

工厂类

使用简单工厂模式(Shape,Circle,Triangle,Rectangle 无需改变,增加工厂类,修改客户端调用逻辑)

代码语言:javascript复制
 public class ShapeSimpleFactory {
 // 简单工厂最核心的地方,通过传入不同的type可以new不同的形状
    public  Shape getShape(String shapeType) {
        if (shapeType == null || "".equals(shapeType)) {
            return null;
        }
        if ("circle".equalsIgnoreCase(shapeType)) {
            return new Circle();
        } else if ("rectangle".equalsIgnoreCase(shapeType)) {
            return new Rectangle();
        } else if ("triangle".equalsIgnoreCase(shapeType)) {
            return new Triangle();
        }
        return null;
    }
}

 客户端(客户端想要创建 圆形,三角形这两个形状,只需要依赖ShapeSimpleFactory)

代码语言:javascript复制
public class SimpleFactoryTest {
    public static void main(String[] args) {
        ShapeSimpleFactory simpleFactory=new ShapeSimpleFactory();
        //传入不同的参数就实现了各种形状的绘制
        simpleFactory.getShape("circle");
        simpleFactory.getShape("triangle");
    }
}

简单工厂类图

适用场景:

  只有一个工厂类,且工厂类根据传入的参数封装了对象的创建过程,所以客户端只需要传入参数,并不关心对象的创建过程。总结一下适用场景:

  (1)需要创建的对象较少。

  (2)客户端不关心对象的创建过程。

优点:只需传入一个正确的参数,就可以获得想要创建的对象

缺点:

1:工厂类的职责相对较重,增加新的产品时,需要修改工厂类的判断逻辑,违背开闭原则

2:不易于扩展过于复杂的产品结构

工厂方法模式

  工厂方法模式是简单工厂的仅一步深化, 在工厂方法模式中,我们不再提供一个统一的工厂类来创建所有的对象,而是针对不同的对象提供不同的工厂。也就是说三角形有三角形的工厂,圆形有圆形的工厂

定义:  定义一个用于创建对象的接口,让子类决定将哪一个类实例化。工厂方法模式让一个类的实例化延迟到其子类。

代码演示:

  创建一个可以绘制不同形状的绘图工具,可以绘制圆形,三角形,长方形这三种图形,每个图形都会有一个draw()方法用于绘图。接口部分定义与简单工厂模式一致

定义一个接口或者抽象类,作为这三个图像的公共父类,并声明draw方法。

代码语言:javascript复制
//定义成抽象类也是可以的,只不过接口是更高一级的抽象,所以习惯定义成接口,而且接口支持多实现,方便后续扩展。
public interface Shape {
    void draw();
}

下面就是编写具体的图形,每种图形都实现Shape 接口

圆形

代码语言:javascript复制
public class Circle implements Shape{

    @Override
    public void draw() {
        System.out.println("圆形");
    }
}

三角形

代码语言:javascript复制
public class Triangle implements Shape{

    @Override
    public void draw() {
        System.out.println("三角形");
    }
}

长方形

代码语言:javascript复制
public class Rectangle implements Shape{

    @Override
    public void draw() {
        System.out.println("长方形");
    }
}

现在我们按照定义所说定义一个工厂接口ShapeFactory

代码语言:javascript复制
public interface ShapeFactory {
//getShape()方法返回我们的Shape 类,
    Shape getShape();
}

接下来我们把上面定义好的每个形状都提供一个工厂类,这些工厂类实现了ShapeFactory。

圆形工厂

代码语言:javascript复制
public class CirleFactory implements ShapeFactory {
    @Override
    public Shape getShape() {
        return new Circle();
    }
}

三角形工厂

代码语言:javascript复制
public class TriangleFactory implements ShapeFactory {
    @Override
    public Shape getShape() {
        return new Triangle();
    }
}

长方形工厂

代码语言:javascript复制
public class RectangleFactory implements ShapeFactory {
    @Override
    public Shape getShape() {
        return new Rectangle();
    }
}

客户端使用(客户端想要创建 圆形,三角形这两个形状)

代码语言:javascript复制
public class FactoryMethodTest {
    public static void main(String[] args) {
        ShapeFactory cirleFactory=new CirleFactory();
        Shape shape= cirleFactory.getShape();
        shape.draw();
        
        ShapeFactory triangleFactory=new TriangleFactory();
        Shape shape1= triangleFactory.getShape();
        shape1.draw();
        
    }
}

 工厂方法类图

和简单工厂对比一下,最根本的区别在于,简单工厂只有一个统一的工厂类,而工厂方法是针对每个要创建的对象都会提供一个工厂类,这些工厂类都实现了一个工厂基类( ShapeFactory)。

适用场景:

  (1)客户端不依赖产品实例如何被创建,实现等细节。

  (2)客户端通过子类来指定创建对应的对象。

优点:

1:用户只需关心所需产品对应的工厂,无需关心创建细节

2:加入新产品符合开闭原则,提高系统的可扩展性。简单工厂增加新产品需求修改工厂类逻辑,而工厂方法只需要新增对应产品 及对应产品的工厂类即可

缺点:

1:类的个数容易过多,增加了代码结构的复杂度

2:增加了系统的抽象性和理解难度

抽象工厂模式

    抽象工厂模式是工厂方法的进一步深化,在这个模式中的工厂类不单单可以创建一个对象,而是可以创建一组对象。这是和工厂方法最大的不同点。

定义:提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。( 在抽象工厂模式中,每一个具体工厂都提供了多个工厂方法用于产生多种不同类型的对象),属于创建型设计模式

实例:创建一个可以绘制不同形状的绘图工具,可以绘制圆形,三角形,长方形这三种形状,每种形状都会有一个draw()方法用于绘图。同时每种类型的图形均有红色,蓝色两种颜色,每种颜色都会有一个Coloring()方法填色。审题可知,三种形状的红色和蓝色应该是我们最终生产的具体产品。所以新建两个抽象产品接口。

颜色类接口

代码语言:javascript复制
public interface Colour {
    void coloring();
}

形状类接口

代码语言:javascript复制
public interface Shape {
    void draw();
}

下面就是编写具体的图形,每种图形都实现Shape 接口

圆形

代码语言:javascript复制
public class CircleShape implements Shape {
    @Override
    public void draw() {
        System.out.println("绘制出圆形的形状");
    }
}
public class CircleColour  implements Colour{

    @Override
    public void coloring() {
        System.out.println("给圆形形状填色");
    }
}

三角形

代码语言:javascript复制
public class TriangleShape implements Shape {
    @Override
    public void draw() {
        System.out.println("绘制出三角形的形状");
    }
}

public class TriangleColour implements Colour{

    @Override
    public void coloring() {
        System.out.println("给三角形的形状填色");
    }
}

长方形

代码语言:javascript复制
public class RectangleShape implements Shape {
    @Override
    public void draw() {
        System.out.println("绘制出长方形的形状");
    }
}
public class RectangleColour implements Colour{

    @Override
    public void coloring() {
        System.out.println("给长方形的形状填色");
    }
}

下面定义一个抽象工厂,该工厂需要可以创建Colour和Shape

代码语言:javascript复制
public interface AbstractFactory {
    Shape drawShape();
    Colour coverColor();
}

在各平台具体的工厂类中完成画形状和填色创建过程

圆形图案

代码语言:javascript复制
public class CircleFactory implements  AbstractFactory {
    @Override
    public Shape drawShape() {
        return new CircleShape();
    }

    @Override
    public Colour coverColor() {
        return new CircleColour();
    }
}

三角形

代码语言:javascript复制
public class TriangleFactory implements AbstractFactory {
    @Override
    public Shape drawShape() {
        return new TriangleShape();
    }

    @Override
    public Colour coverColor() {
        return new TriangleColour();
    }
}

长方形

代码语言:javascript复制
public class RectangleFactory implements AbstractFactory {
    @Override
    public Shape drawShape() {
        return new RectangleShape();
    }

    @Override
    public Colour coverColor() {
        return new RectangleColour();
    }
}

客户端调用:(绘制出红圆形图案)

代码语言:javascript复制
    public class AbstractFactoryTest {
    public static void main(String[] args) {
        AbstractFactory abstractFactory=new CircleFactory();
       Shape shape= abstractFactory.drawShape();
       shape.draw();
      Colour colour=abstractFactory.coverColor();
      colour.coloring();
    }
}

抽象工厂类图:

针对不同图案只通过创建不同的工厂对象就完成了颜色和形状的创建。下面总结一下抽象工厂的适用场景。

适用场景

(1)和工厂方法一样客户端不需要知道它所创建的对象的类。

(2)强调一系列相关的产品对象(属于统一产品族)一起使用创建对象需要大量重复的代码

(3)系统结构稳定,不会频繁的增加对象。(因为一旦增加就需要修改原有代码,不符合开闭原则)

优点:

1:具体产品在应用层代码隔离,无需关心创建细节

2:将一个系列的产品族统一到一起创建

缺点:

1:规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口

2:增加了系统的抽象性和理解难度。

应用实例

Spring框架中的DefaultListableBeanFactory

以上就是三种工厂模式的总结,如有不对之处还希望各位留言指正,以免误导他人。

0 人点赞