前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >工厂模式

工厂模式

作者头像
胖虎
发布2019-06-26 17:07:30
4360
发布2019-06-26 17:07:30
举报
文章被收录于专栏:晏霖

前言

在23中设计模式中,工厂方法属于创建型的设计模式,只有工厂方法和抽象工厂两种,但是实际我们常与简单工厂混淆,因为简单工厂模式违背了开闭原则。

什么是开闭原则:开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类,后面的具体设计中我们会提到这点。

所以简单工厂不属于设计模式内的,但是并不是说简单工厂是错误的,只是根据具体情况使用而已。

下面我就针对简单工厂、工厂方法、抽象工厂结合Demo演示给大家。

正文

如图,就是工厂模式的划分。

简单工厂

概念:一个工厂类根据传入的参量决定创建出那一种产品类的实例。

想象一下汽车生产厂生产汽车,有两个工厂,分别是宝马和奔驰,客户想要买这两种车,就要分别去这两个工厂去买,结合在代码里就是客户分别传递不同的参数才可以得到不同的对象。

首先我们需要一个接口,用来返回不同的品牌的汽车。

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

然后我们需要两个汽车

代码语言:javascript
复制
public class Benz implements Car {
    public void produce() {
        System.out.println("生产一辆奔驰");
    }
}
代码语言:javascript
复制
public class BMW implements Car {
    public void produce() {
        System.out.println("生产一辆宝马");
    }
}

接下来就是工厂,这个工厂就是根据客户传过来的不同参数返回不同的汽车。

代码语言:javascript
复制
public class CarFactory {
    public Car produce(String type) {
        if ("bmw".equals(type)) {
            return new BMW();
        } else if ("benz".equals(type)) {
            return new Benz();
        } else {
            System.out.println("类型错误");
        }
        return null;
    }
}

最后来了一个顾客说是要买宝马,让我们来测试一下吧

代码语言:javascript
复制
public class SimpleFactoryTest {
    public static void main(String[] args) {
        CarFactory factory = new CarFactory();
        Car car = factory.produce("bmw");
        car.produce();
    }
}

大家看代码可以得知,现在是两个车,就要写两个if去判断,如果以后出现很多个产品那么就就要在工厂方法里写多个if ,这样就会造成拓展业务需要修改原有代码来实现,这样的写法可以实现,但是很low,建议同学们尝试以下两种。

工厂方法模式

概念:定义一个创建对象的接口,让子类决定实例化那个类。

工厂模式细分的话有两种,我在代码里会讲解一种,另一种在示例代码中体现,被我注释掉的就是普通工厂方法,大家一看便知。

与简单工厂重复的代码我就贴在一个代码块中了。

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

public class Benz implements Car {
    public void produce() {
        System.out.println("生产一辆奔驰");
    }
}

public class BMW implements Car {
    public void produce() {
        System.out.println("生产一辆宝马");
    }
}

不同的地方就是工厂的写法,我们一个汽车品牌就新建一个工厂方法。

代码语言:javascript
复制
public class BenzCarFactory {
    /**
     * 工厂方法
     * @return
     */
//    public Car produceBenz() {
//        return new Benz();
//    }

    /**
     * 静态工厂方法
     *
     * @return
     */

    public static Car produceBenz() {
        return new Benz();
    }
}
代码语言:javascript
复制
public class BMWCarFactory {
    /**
     * 工厂方法
     * @return
     */
//    public Car produceBMW() {
//        return new BMW();
//    }
    
    /**
     * 静态工厂方法
     *
     * @return
     */
    public static Car produceBMW() {
        return new BMW();
    }
}

因为只静态的方法,那么在jvm加载时就已经创建了,所以我们在引用的时候就不用new工厂对象了,这也是普通工厂方法与静态工厂方法的区别所在。

让我们看一下客户是怎么购买汽车的。

代码语言:javascript
复制
public class FactoryMethodTest {
    //psvm
    public static void main(String[] args) {
        /**
         * 工厂方法
         */
//        BenzCarFactory factory = new BenzCarFactory();
//        Car car = factory.produceBenz();
//        car.produce();

        /**
         * 静态工厂方法
         */
        Car car = BenzCarFactory.produceBenz();
        car.produce();
    }
}

可以看出,每个工厂只生产一种产品,客户端通过不同的工厂去生产不同的产品。这样做的好处就是我们对业务进行拓展时不用更改代码,只需要新增一个拓展对产品或者对象就可以,这也是最简单也是我认为最常用对工厂方法了。

抽象工厂

概念:创建相关或依赖对象的家族,而无需明确指定具体类。

抽象工厂适用于复杂业务需求,复杂的产品生产场景中。怎么复杂呢?就是产品属性多了一个纬度,之前我们都是生产汽车,但是现在要区分出生产的颜色,对汽车的要求不仅仅是品牌还有颜色了。

来看看具体的代码实现:

首先定义三种颜色的接口

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

public interface Red {
    void create();
}


public interface White {
    void create();
}

然后定义我们存在的产品,我们现在只有黑色奔驰,黑色宝马,白色奔驰,白色宝马,红色奥迪。分别创建这五个产品的类。

代码语言:javascript
复制
public class BenzBlack implements Black {
    public void create() {
        System.out.println("黑色奔驰");
    }
}

public class BenzWhite implements White {
    public void create() {
        System.out.println("白色奔驰");
    }
}


public class BMWBlack implements Black {
    public void create() {
        System.out.println("黑色宝马");
    }
}

public class BMWWhite implements White {
    public void create() {
        System.out.println("白色宝马");
    }
}

public class RedAudi implements Red {
    public void create() {
        System.out.println("红色奥迪");
    }
}

然后我们定义工厂接口,工厂接口是把刚才颜色接口进行了统一整理在一起。说明我们现在可以生产这三种颜色任意品牌汽车。

所以说对业务拓展性非常高。

代码语言:javascript
复制
public interface CarFactory {
    Black black();

    White white();

    Red red();
}

那么就让我们随意创建三种汽车的工厂。

代码语言:javascript
复制
public class AudiFactory  implements CarFactory{
    public Black black() {
        return null;
    }

    public White white() {
        return null;
    }

    public Red red() {
        return new RedAudi();
    }
}

public class BenzFactory implements CarFactory {
    
    public Black black() {
        return  new BenzBlack();
    }

    public White white() {
        return new BenzWhite();
    }

    public Red red() {
        return null;
    }
}

public class BMWFactory implements CarFactory {
    public Black black() {
        return new BMWBlack();
    }

    public White white() {
        return new BMWWhite();
    }

    public Red red() {
        return null;
    }
}

让我们来测试一下

代码语言:javascript
复制
public class AbstractFactoryMethodTest {
    public static void main(String[] args) {
        AudiFactory audi = new AudiFactory();
        Red redAudi = audi.red();
        redAudi.create();

        BenzFactory benz = new BenzFactory();
        Black blackBenz = benz.black();
        blackBenz.create();

    }
}

输出结果如下

如果要对以上代码有疑问,或者想要代码,可以加我微信 15524579896

总结

简单工厂模式适用于工厂类需要创建的对象比较少的情况,客户只需要传入具体的参数,就可以忽略工厂的生产细节,去获取想要的对象;

工厂方法模式,主要是针对单一产品结构的情景,拓展时只需增加一个工厂类就可以;

抽象工厂模式则是针对多级产品结构(系列产品)的一种工厂模式,拓展时增加多个类,改动比较大;

最后在说一下,每种模式都有自己的优点和弊端,没有最好的模式,只有最适合的模式,只要符合实际开发需求就是最好的。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-02-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 晏霖 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 正文
    • 简单工厂
    • 工厂方法模式
      • 抽象工厂
        • 总结
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档