设计模式之工厂模式与工厂方法模式

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式之工厂模式与工厂方法模式相关的知识,希望对你有一定的参考价值。

工厂模式类图

技术分享图片

简单工厂模式代码

package pattern.factory;

/**
 * @ClassName IShape
 * @Description TODO:描述该接口职责
 * @Author ckmike
 * @Date 18-12-14 上午11:33
 * @Version 1.0
 * @Copyright ckmike
 **/
public interface IShape {
    void draw();
    double area();
}

package pattern.factory;

/**
 * Circle 简要描述
 * <p> TODO:描述该类职责 </p>
 *
 * @author ckmike
 * @version 1.0
 * @date 18-12-14 上午11:34
 * @copyright ckmike
 **/
public class Circle implements IShape {

    private double r;

    public Circle(double r) {
        this.r = r;
    }

    @Override
    public void draw() {
        System.out.println("绘制r:"+this.r+"圆形。");
    }

    @Override
    public double area() {
        return Math.PI*this.r*this.r;
    }
}

package pattern.factory;

/**
 * Rectangle 简要描述
 * <p> TODO:描述该类职责 </p>
 *
 * @author ckmike
 * @version 1.0
 * @date 18-12-14 上午11:34
 * @copyright ckmike
 **/
public class Rectangle implements IShape {

    private double width;
    private double height;

    public Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }

    @Override
    public void draw() {
        System.out.println("绘制width="+this.width+",height="+this.height+"矩形。");
    }

    @Override
    public double area() {
        return this.width*this.height;
    }
}

package pattern.factory;

/**
 * Square 简要描述
 * <p> TODO:描述该类职责 </p>
 *
 * @author ckmike
 * @version 1.0
 * @date 18-12-14 上午11:35
 * @copyright ckmike
 **/
public class Square implements IShape {

    private double width;

    public Square(double width) {
        this.width = width;
    }

    @Override
    public void draw() {
        System.out.println("绘制width:"+this.width+"正方形。");
    }

    @Override
    public double area() {
        return this.width*this.width;
    }
}

package pattern.factory;

/**
 * @FileName ShapeType
 * @Description TODO:描述该枚举职责
 * @Author ckmike
 * @Date 18-12-14 下午12:34
 * @Version 1.0
 * @Copyright ckmike
 **/
public enum ShapeType {

    /**
     * 圆形
     **/
    Circle("Circle", 1),
    /**
     * 矩形
     **/
    Rectangle("Rectangle", 2),
    /**
     * 正方形
     **/
    Square("Square",3);

    private String name;
    private int index;

    private ShapeType(String name, int index) {
        this.name = name;
        this.index = index;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    public int getIndex() {
        return index;
    }
    public void setIndex(int index) {
        this.index = index;
    }
}

package pattern.factory;

/**
 * ShapeFactory 简要描述
 * <p> TODO:描述该类职责 </p>
 *
 * @author ckmike
 * @version 1.0
 * @date 18-12-14 下午12:12
 * @copyright ckmike
 **/
public class ShapeFactory {

    // 获取指定类型的图形对象
    public static IShape getShape(String type,double... paramters){
        switch (type){
            case "Circle":
                return new Circle(paramters[0]);
            case "Rectangle":
                return new Rectangle(paramters[0],paramters[1]);
            case "Square":
                return new Square(paramters[0]);
            default:
                {
                    System.out.println("图形:"+type+"不存在,请确认后重写设置.");
                    return null;
                }
        }
    }
}

package pattern;

import pattern.factory.IShape;
import pattern.factory.ShapeFactory;
import pattern.factory.ShapeType;

/**
 * FactoryDemo 简要描述
 * <p> TODO:描述该类职责 </p>
 *
 * @author ckmike
 * @version 1.0
 * @date 18-12-14 上午11:32
 * @copyright ckmike
 **/
public class FactoryDemo {

    public static void main(String[] args) {
        IShape circle = ShapeFactory.getShape(ShapeType.Circle.getName(), 10);
        circle.draw();
        System.out.println("面积:"+circle.area());
    }
}

技术分享图片
说明:
简单工厂模式适合:凡是出现了大量的产品需要创建,并且具有共同的接口时,可以通过工厂方法模式进行创建。

分析:
对于上述的工厂模式,我们如果需要新增加一个图形,那么我们需要:
1.创建图形类,实现IShape接口
2.在枚举类中新增一个常量对应该图形类
3.需要修改ShapeFactory类的getShape方法,添加case
这种模式并不符合开关原则。针对这个问题我们可以这么做如下:
技术分享图片
分析:这种方式不需要ShapeType枚举类,不需要修改ShapeFactory类,但是这样针对每一个对象去设置工厂类会存在一个问题就是会有大量的对象工厂类,虽然符合开关原则。有点就是:新增图形时,只要增加一个图形类和对应的工厂类。缺点就是会有大量的对象工厂类。这种方式就是工厂方法模式。

工厂方法模式

技术分享图片

分析:工厂方法模式代码我就不写了,因为这张类图就非常清晰的表示了,结合工厂模式的理解,你就可以很轻松的实现这个模式。这个模式符合开关原则。缺点就是会有大量的具体工厂类。工厂模式与工厂方法模式的选择取决于你对未来扩展要求的判断,如果未来扩展可能性极地甚至不可能,那么就可以选择工厂模式,如果未来扩展要求非常强烈且可能性很大选择工厂方法模式更为合适,尽管会增加大量的具体工厂类,但不需要修改原来的代码。

以上是关于设计模式之工厂模式与工厂方法模式的主要内容,如果未能解决你的问题,请参考以下文章

设计模式:简单工厂工厂方法抽象工厂之小结与区别

Java代码实现设计模式之工厂模式

设计模式之简单工厂模式

《JAVA与模式》之工厂方法模式

34面向对象设计模式之工厂模式——简单工厂模式与工厂方法模式比较

设计模式之工厂方法模式