设计模式-工厂方法模式

上一篇文章 设计模式-简单工厂模式 介绍了简单工厂模式

简单工厂模式违背了”开放 – 关闭原则”,工厂类集中了所有产品(实例)的创建逻辑,违反了高内聚责任分配原则

为了解决这些问题,学习一下工厂方法模式

厂方法模式:

工厂方法模式,又称工厂模式/多态工厂模式/虚拟构造器模式

在工厂方法模式中,定义了一个创建产品对象的接口,将实际产品(实例)的创建逻辑延迟到了接口其子类(具体工厂)当中

工厂类成为了抽象工厂角色,不再负责产品的创建

这样进一步的抽象化,使得系统在不修改具体工厂的情况下,添加新的产品

模式中包含的角色及职责:

抽象产品(Product)角色:具体产品的父类 ,用于描述产品的公共接口

具体产品(Concrete Product)角色:抽象产品的子类,工厂类创建的目标类,即产品

抽象工厂(Creator)角色:具体工厂的父类,用于描述及具体工厂的公共接口

具体工厂(Concrete Creator)角色:抽象工厂的子类,被外界调用,用于实例化具体产品对

使用方法

1.定义抽象产品类/定义产品公共接口

2.定义具体实现产品类

3.创建抽象工厂类

4.定义具体实现工厂类

5.外界调用具体工厂类,创建产品实例

实例:

实例代码已上传到GitLab,地址:https://gitlab.com/louisvv/DesignPattern

背景:有一个水果工厂,用来生产水果,现在有两种水果:苹果、香蕉

目的:通过工厂方法模式实现两种水果的生产

步骤如下:

1.定义抽象产品类Fruit

public abstract class Fruit {
    public abstract void show();
}

2.定义具体实现产品类

苹果类:

public class Apple extends Fruit {
    public void show(){
        System.out.println("我是苹果");
    }
}

香蕉类:

public class Banana extends Fruit {
    public void show(){
        System.out.println("我是香蕉");
    }
}

3.定义抽象工厂类

public interface FruitFactory {
    public Fruit getFruit();
}

4.定义具体实现工厂类

定义苹果工厂类:

public class AppleFactory implements FruitFactory{
    public Fruit getFruit() {
        return new Apple();
    }
}

定义香蕉工厂类:

public class BananaFactory implements FruitFactory {
    public Fruit getFruit() {
        return new Banana();
    }
}

5.定义用户类,外部调用具体工厂,创建实例对象

public class User {
    public static void main(String[] args) {
        //  创建苹果工厂
        FruitFactory appleFactory = new AppleFactory();
        //  通过苹果工厂创建苹果实例对象
        Fruit apple = appleFactory.getFruit();
        apple.show();

        //  创建香蕉工厂
        FruitFactory bananaFactory = new BananaFactory();
        //  通过香蕉工厂创建香蕉实例对象
        Fruit banana = bananaFactory.getFruit();
        banana.show();
    }
}

结果:

我是苹果
我是香蕉

现在工厂中新添了一种水果,桃子,我们需要作如下几个步骤:

1.定义具体实现产品类,即桃子类

public class Peach extends Fruit{
    public void show() {
        System.out.println("我是桃子");
    }
}

2.定义具体实现工厂类,即桃子工厂类

public class PeachFactory implements FruitFactory {
    public Fruit getFruit() {
        return new Peach();
    }
}

3.在用户类中,新添一个桃子工厂,并通过桃子工厂创建桃子实例对象

  //  创建桃子工厂
        FruitFactory peachFactory = new PeachFactory();
        //  通过桃子工厂创建桃子实例对象
        Fruit peach = new Peach();
        peach.show();

结果:

我是苹果
我是香蕉
我是桃子

至此,通过和简单工厂方法对比,我们发现,工厂方法模式,当我们新添一种水果时, 不违背“开放-关闭”原则,因为我们新添加一类水果时,不需要修改原有工厂类,而是新添加一个具体工厂

现在我们对工厂方法模式的优缺点做以总结:

优点:

1.更符合开-闭原则,扩展性高

新增一种产品时,只需要增加相应的具体产品类和相应的工厂子类即可
简单工厂模式需要修改工厂类的判断逻辑

2.符合单一职责原则

每个具体工厂类只负责创建对应的产品
简单工厂中的工厂类存在复杂的逻辑判断

3.不使用静态工厂方法,可以形成基于继承的等级结构

简单工厂模式的工厂类使用静态工厂方法

缺点:

1.添加新产品时,除了增加新产品类外,还要增加与之对应的具体工厂类,增加了开发量;同时,有更多的类需要编译和运行,会给系统带来一些额外的开销;

2.虽然保证了工厂方法内的对修改关闭,但对于使用工厂方法的类,如果要更换另外一种产品,仍然需要修改实例化的具体工厂类;

3.一个具体工厂只能创建一种具体产品

适用场景:

1.对于某个产品,调用者清楚地知道应该使用哪个具体的工厂来服务,实例化该具体工厂,生产出具体的产品来;

2.只是需要一种产品,而不想知道也不需要知道工厂是如何生产出来的,只需要知道具体对应的工厂就行。


举个例子:

当我们系统需要访问外部数据源,有多种数据源选择(mysql、oracle、hdfs、mangodb等),用户不确定使用哪种数据源,或者新添了一种数据源,可以使用工厂方法模式,进行设计开发

亲,点个赞吧!

赫墨拉

我是一个喜爱大数据的小菜鸡,这里是我分享我的成长和经历的博客

You may also like...

1 Response

发表评论

邮箱地址不会被公开。