美文网首页Android首页投稿(暂停使用,暂停投稿)程序员
简单工厂模式,工厂方法模式,抽象工厂模式(从放弃到入门)

简单工厂模式,工厂方法模式,抽象工厂模式(从放弃到入门)

作者: DakerYi | 来源:发表于2016-10-31 15:04 被阅读976次

    工厂模式,很多讲设计模式的书中,工厂模式都是第一个讲的模式,因为其最简单。但是在实际开发中,工厂模式是非常常见的。在java开发中经常遇到一个类叫 xxxFactory,虽然不是所有带 Factory的类都是工厂模式,但是肯定是有一定原因的,今天我们顺便分析一下Android中一个重要的Factory类: BitmapFactory。

    首先我们来看看什么是工厂模式

    简单工厂模式

    有一个形状(Shape)接口,包含一个方法sayHello() 输出自己的信息,然后现在有3中形状,圆,三角形,矩形。

    因为比较简单,直接上类图:

    1.png

    Shape.java

    public interface Shape {
        void sayHello();
    }
    

    Circle.java

    public class Circle implements Shape {
    
        @Override
        public void sayHello() {
            System.out.println("I am circle");
        }
    
    }
    

    Triangle.java

    public class Triangle implements Shape {
    
        @Override
        public void sayHello() {
            System.out.println("I am triangle");
        }
    
    }
    

    Rectangle.java

    public class Rectangle implements Shape {
    
        @Override
        public void sayHello() {
            System.out.println("I am rectangle");
        }
    
    }
    

    如果不使用工厂模式,我们这样使用,每种形状直接用new生成。客户端与具体的类耦合

    Shape circle = new Circle();
    circle.sayHello();
    
    Shape rectangle = new Rectangle();
    rectangle.sayHello();
    

    如果使用简单工厂模式呢?

    ShapeFactory.java

    public class ShapeFactory {
        
        public static final String CIRCLE = "circle";
        public static final String RECTANGLE = "rectangle";
        public static final String TRIANGLE = "triangle";
    
        public static Shape create(String name) {
            Shape shape = null;
            if (name == null)
                throw new NullPointerException();
    
            if (name.equals("circle")) {
                shape = new Circle();
            } else if (name.equals("rectangle")) {
                shape = new Rectangle();
            } else if (name.equals("triangle")) {
                shape = new Triangle();
            } 
            return shape;
        }
    
    }
    

    简单工厂类是通过静态方法 create 创建 Shape,通过name指定创建那种形状。client可以这样使用工厂类:

    Shape shape = ShapeFactory.create(ShapeFactory.CIRCLE);
    shape.sayHello();
    

    client 中都看不到Circle类,我只知道,传入 circle 我可以得到一个圆形。由于client中看不到Circle类,所以这是是在解耦。由于 ShapeFactory 是根据字符串来创建所需要的类,如果和 Java的反射机制相结合,可以设计出更加解耦的系统。例如在ShapeFactory中,直接使用反射构造类,那么name就需要传入具体的报名加类。这是不是看起来和一个东西很像,对没错,就是Spring的 BeanFactory 机制,利用配置文件 <bean>...</bean>得到要初始化类的名称,然后通过BeanFactory 反射机制创建出类,并注入到系统中,经典的IOC机制。感兴趣的童鞋可以去研究研究

    简单工厂的缺点

    如果按照上面的写法,不使用java的反射,扩展性是很差的。如果添加一种形状,必须修改先前代码中的判断。所以我们来介绍一下工厂方法模式。

    工厂方法模式

    工厂方法模式的重点在于,产品和工厂是同级的,一种具体的产品对应一种商品。其实这样说是不准确的,应该是一类具体的产品。来看看例子:

    先看类图:

    2.png

    类图的左边部分没有改变,不贴代码,主要修改右边:

    ShapeFactory .java

    public interface ShapeFactory {
        Shape create();
    }
    

    CircleFactory.java

    public class CircleFactory implements ShapeFactory {
        @Override
        public Shape create() {
            return new Circle();
        }
    }
    

    RectangleFactory.java

    public class RectangleFactory implements ShapeFactory {
        @Override
        public Shape create() {
            return new Rectangle();
        }
    }
    

    TriangleFactory.java

    public class TriangleFactory implements ShapeFactory {
        @Override
        public Shape create() {
            return new Triangle();
        }
    }
    

    扩展性

    1. 如果这个时候还要添加一种新的形状,只需添加对应的形状和工厂类。例如五角星类:

    Star.java

    public class Star implements Shape {
        @Override
        public void sayHello() {
            System.out.println("I am Star");
        }
    }
    

    StarFactory.java

    public class StarFactory implements ShapeFactory {
        @Override
        public Shape create() {
            return new Star();
        }
    }
    
    1. 如果这个时候添加的不是全新的形状呢?比如正三角形,直角三角形?我们还需要添加新的工厂吗?

    不需要,直接继承自三角形Triangle就行,因为它们是属于三角形这个大类的,如果再添加工厂,不仅类太多,也损失了它们本来就是三角形的一种的特性

    抽象工厂模式

    抽象工厂模式和工厂方法模式,其实离得挺近的。抽象工程模式在其基础上添加了产品族的概念。
    来看看书上的定义:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类

    看类图:

    3.png

    ShapeFactory是制造带颜色的形状的工厂类,它是一个抽象工厂,提供了一个产品族(形状,颜色)的创建接口。具体的实现交给之类去实现,例如创建红色的圆,白色的圆,红色三角形,白色三角形等。其实工厂方法模式蕴含其中,不知你能不能体会,把颜色和形状拆开,就是工厂方法模式。

    抽象工程模式的有点就在于,提供了一个更加抽象一点的产品构造,产品产品族组成的,至于怎么组成,自己去实现,而我只定义这类抽象产品组到底有哪些。这样应该更好理解一点。

    代码就稍微贴一点:

    Color.java

    public interface Color {
        void sayHello();
    }
    

    Red.java

    public class Red implements Color{
        @Override
        public void sayHello() {
            System.out.println("in Red");
        }
    }
    

    White.java

    public class White implements Color{
        @Override
        public void sayHello() {
            System.out.println("in White");
        }
    }
    

    抽象工厂:

    ShapeFactory .java

    public interface ShapeFactory {
        Shape createShape();
        Color createColor();
    }
    

    具体工厂:

    RedCircleFactory .java

    public class RedCircleFactory implements ShapeFactory {
        @Override
        public Shape createShape() {
            return new Circle();
        }
    
        @Override
        public Color createColor() {
            return new Red();
        }
    }
    

    WhiteCircleFactory .java

    public class WhiteCircleFactory implements ShapeFactory {
        @Override
        public Shape createShape() {
            return new Circle();
        }
    
        @Override
        public Color createColor() {
            return new White();
        }
    }
    

    总结

    三种工厂模式,我想说的是,不是越后面就越高端,关键在看运用的场合。这篇就先写到这里吧,如果后面有时间,再写一篇专门看看几种工厂模式中在Spring或者Android中的应用。其实工厂模式是很常见的,大家尽量掌握。

    相关文章

      网友评论

      本文标题:简单工厂模式,工厂方法模式,抽象工厂模式(从放弃到入门)

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