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

工厂模式,很多讲设计模式的书中,工厂模式都是第一个讲的模式,因为其最简单。但是在实际开发中,工厂模式是非常常见的。在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中的应用。其实工厂模式是很常见的,大家尽量掌握。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容