深入浅出工厂设计模式

工厂设计模式

一.什么是工厂设计模式

工厂模式是我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式。因为工厂模式就相当于创建实例对象的new,虽然这样做,可能多做一些工作,但会给你系统带来更大的可扩展性和尽量少的修改量。工厂模式最直接的作用就是将创建对象和对象的业务逻辑相分离。

工厂模式最常见的三种:

  • 简单工厂模式
  • 工厂方法模式
  • 抽象工厂

二、简单工厂模式

以下是我看《headefirst设计模式》的工厂模式的笔记。非常有意思,但是篇幅有点长,所以打算总结下,写个简洁版的。

假如你有个pizza店,你可以为客人做很多 pizza。

首先,你需要很多pizza对象,定义一个pizza抽象类:

public abstract class Pizza {
    abstract void prepared();
    abstract void bake();
    abstract void cut();
    abstract void box();
}

中式 pizza:

public class ChineasePizza extends Pizza {
    @Override
    public void prepared() {

    }

    @Override
    public void bake() {

    }

    @Override
    public void cut() {

    }

    @Override
    public void box() {

    }
}

美式pizza:

public class AmericanPizza extends Pizza {
    @Override
    public void prepared() {

    }

    @Override
    public void bake() {

    }

    @Override
    public void cut() {

    }

    @Override
    public void box() {

    }
}

当我需要为客人准备一份pizza,我们可能会需要这样写:

public Pizza orderPizza(String type){
        Pizza pizza = null;
        if(type.equals("c")){
            pizza=new ChineasePizza();
        }else if(type.equals("a")){
            pizza=new AmericanPizza();
        }else if(type.equals("e")){
            pizza=new EnglishPizza();
        }else {
            pizza=new ChineasePizza();
        }
        pizza.prepared();
        pizza.bake();
        pizza.cut();
        pizza.box();
        return pizza;
    }

当你有很多种pizza的时候,这个else if()特别的长:

 if(type.equals("c")){
            pizza=new ChineasePizza();
        }else if(type.equals("a")){
            pizza=new AmericanPizza();
        }else if(type.equals("e")){
            pizza=new EnglishPizza();
        }else if(...){
        ....
        }else {
            pizza=new ChineasePizza();
        }

你需要创建一个工厂来管理这些pizza的创建实例:

public class SimplePizzaFactory {

    public Pizza createPizza(String type) {

        Pizza pizza = null;
        if(type.equals("c")){
            pizza=new ChineasePizza();
        }else if(type.equals("a")){
            pizza=new AmericanPizza();
        }else if(type.equals("e")){
            pizza=new EnglishPizza();
        }else {
            pizza=new ChineasePizza();
        }

        return pizza;
    }
}

有了工厂之后的你代码应该这样写:

public class PizzaStore {

    private SimplePizzaFactory simplePizzaFactory;
    public PizzaStore(SimplePizzaFactory simplePizzaFactory){
        this.simplePizzaFactory=simplePizzaFactory;
    }

    public Pizza orderPizza(String type) {
       Pizza pizza= simplePizzaFactory.createPizza(type);
        pizza.prepared();
        pizza.bake();
        pizza.cut();
        pizza.box();
        return pizza;
    }
}

就是简单的工厂模式,工厂处理创建对象的细节。工厂模式将创建对象和对象的业务逻辑相分离,降低了代码的耦合性,提高了代码的可读性。

三、工厂方法模式

当你需要开很多pizza店的时候,你可能需要创建的pizztore抽象类,这个抽象类只专注于卖pizza的业务逻辑,不专注pizza是怎么来的:

public abstract class APizzaStore {

    public Pizza orderPizza(String type) {
        Pizza pizza= createPizza(type);
        pizza.prepared();
        pizza.bake();
        pizza.cut();
        pizza.box();
        return pizza;
    }
    abstract Pizza createPizza(String type);
}

它的子类需要专注于pizza 是怎么来的,你需要在北京开一家pizza店:

public class BeijingtPizzaStore extends APizzaStore{

    @Override
    Pizza createPizza(String type) {
        Pizza pizza;
        if(type.equals("a")){
            pizza=new AmericanPizza();
        }else {
            pizza=new ChineasePizza();
        }
        return pizza;
    }
}

你在北京卖pizza之需要:

BeijingtPizzaStore bps=new BeijingtPizzaStore();
bps.orderPizza();

同理,你需要在深圳开pizza店:

 public class ShenZhengPizzaStore extends APizzaStore {
    @Override
    Pizza createPizza(String type) {
        return null;
    }
}

工厂方法用来处理对象的创建,并将这样的行为封装在子类中。超类的代码和子类的对象创建代码就解耦了。

四、抽象工厂模式

你制造pizza的时候,需要很多原料,这时需要一个工厂来制造:

public interface IngredientFactory {
    Dauch createDauch();
    Sauce createSauch();
    Cheese createCheese();
}

创建一个中国原料工厂:

public class ChineaseIngredientFactory implements IngredientFactory {
    @Override
    public Dauch createDauch() {
        return new Dauch();
    }

    @Override
    public Sauce createSauch() {
        return new Sauce(); //这里我简便的写,其实也可以说Sauch的子类。
    }

    @Override
    public Cheese createCheese() {
        return new Cheese();
    }
}

同理也可以创建美国原料工厂:

这时我们可以重做pizza:

public abstract class Pizza {    

    String name;                 
    Dauch dauch;                 
    Sauce sauch;            
    Cheese  cheese ;     

    abstract void prepared();    
    abstract void bake();        
    abstract void cut();         
    abstract void box();         
}                                

中国式pizza:

public class ChineasePizza extends Pizza {

    private ChineaseIngredientFactory ingredientFactory;

    public ChineasePizza(ChineaseIngredientFactory ingredientFactory){
        this.ingredientFactory=ingredientFactory;
    }
    @Override
    public void prepared() {
        dauch=ingredientFactory.createDauch();
        sauch=ingredientFactory.createSauch();
        cheese=ingredientFactory.createCheese();
        //TODO

    }

    @Override
    public void bake() {
        //TODO
    }

    @Override
    public void cut() {
        //TODO
    }

    @Override
    public void box() {
        //TODO
    }
}

这时候我们再看,利用抽象工厂模式,可以为pizza创建原料,pizza只关注于它自身的业务逻辑,而不用关注pizza原料从哪里来,这样的pizza和pizza原料的解耦。

通过抽象工厂所提供的接口,可以创建产品的家族,利用这个接口写代码,我们的代码将实际工厂解耦,以便在不同的工厂,制造出不同的产品。

到此为止,三种工厂模式已经讲解完毕,源码下载

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏测试开发架构之路

Java基础知识学习笔记(一)

  理解面向对象: Java纯粹的面向对象的程序设计语言,主要表现为Java完全支持面向对象的三个基本特征:继承、封装、多态。 Java程序的最小单位是类,类代...

34714
来自专栏哲学驱动设计

如何学习框架

方法一: *以各种方式了解这个框架产生的原因,及其主要解决的问题。1% *观察其主要外部接口(这里的外部接口是指公有类型)的使用场景,理解它的核心概念。5% *...

1928
来自专栏Java Web

Java学习笔记(0)——了解Java前言:正式开始之前

文 / 我没有三颗心脏 前言: 这里是一些关于写文的原因,目的和其他的有的没的,跟Java没有一点关系,如果是想要学习干货的童鞋可以直接跳过。 系列文章最开...

3117
来自专栏贾老师の博客

【笔记】抽象泄漏

883
来自专栏TEG云端专业号的专栏

【Augustzhang 张元龙】知根知底,方能游刃有余

小编语:据江湖传闻,龙哥从初中就开始写代码,高中通过计算机竞赛免试上了大学,大学里则是ACM大神。2010年毕业加入腾讯,先后从事密保、验证码等后台研发工作,...

3194
来自专栏一个会写诗的程序员的博客

《Spring Boot极简教程》附录2 编程的本质N小结

尼古拉斯·沃斯(Niklaus Wirth,1934年2月15日—),生於于瑞士温特图尔,是瑞士计算机科学家。Pascal语言之父。

643
来自专栏软件成本造价评估

软件造价之:浅析快速功能点方法度量软件的规则及过程

快速功能点方法是一种软件规模度量方法。该方法适用于软件项目早期、中期、后期等各个阶段的规模估算或测量。   采用优化后的功能点方法——快速功能点方法进...

750
来自专栏ThoughtWorks

《面向对象的思考过程》应该是怎样的?

作者:Matt Weisfeld 仅学习一种特定的开发方法、一种编程语言或者一组设计工具并不能说明学会了“面向对象”这一概念。简单来说,以面向对象方式编程就是一...

3598
来自专栏CDA数据分析师

译文|数据建模有新招!

本文由CDA数据分析研究院翻译,译者:王晨光,转载必须获得本站、原作者、译者的同意,拒绝任何不表明译者及来源的转载! 在过去的三十年,ERP,CRM和Analy...

1846
来自专栏企鹅号快讯

如何快速学习C语言?系统学习路线奉上

C语言的重要性 C语言作为编程行业必备的基础,它引入N多的库可以用来开发比较复杂的图形程序,如:俄罗斯方块,如:操作数据库的界面,但是它的意义不在于开发图形界面...

1826

扫码关注云+社区