成为架构师的必经之路-掌握软件设计模式(二)

举报
小滴课堂 发表于 2022/03/30 14:48:53 2022/03/30
【摘要】 从原生社会的过渡-常见的工厂设计模式你认识了多少「工厂设计模式的介绍」工厂模式它提供了一种创建对象的最佳方式,就是我们在创建对象的时候不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。比如说,需要去购买一辆车,你会想车辆是如何进行组装吗?这并不需要,只需要去购买你想要的车的类型就可以,车的类型有轿车、跑车、SUV,直接去4S店购买即可(这个4S店就是工厂)。在日常可以...

从原生社会的过渡-常见的工厂设计模式你认识了多少

「工厂设计模式的介绍」

工厂模式它提供了一种创建对象的最佳方式,就是我们在创建对象的时候不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。比如说,需要去购买一辆车,你会想车辆是如何进行组装吗?这并不需要,只需要去购买你想要的车的类型就可以,车的类型有轿车、跑车、SUV,直接去4S店购买即可(这个4S店就是工厂)。在日常可以看到,工厂生产电脑,但它只是生产品牌A的电脑吗?并不是的,还有B、C、D品牌电脑。在业务的开发中,支付可以说是很常见了,里面有统一下单和支付接口,具体的支付实现可以有微信、支付宝、银联等等。


用户调用了工厂类的CatFactory类来生成了一个CatService,用户就不需要了解到CatService类的实现过程,用户需要某一个类的时候就只需要调用它的工厂类,然后会返回一个实例给用户。

工厂模式有三种不同的方式实现

1、简单工厂模式:通过传入相关的类型来返回相对应的类,这种方式比较单一,可扩展性相对较差

2、工厂方式模式:通过实现类实现相对应的方法来决定所对应的返回结果,这种方式的可扩展性比较强

3、抽象工厂模式:基于上述的两种模式的拓展,并且支持细化产品。

「应用场景」

那么工厂模式它的应用场景有哪些呢?

解耦:分离职责,把复杂的对象的创建和使用的过程分开

复用代码,降低项目的维护成本:如果对象创建复杂并且多出需要用到,如果每一个地方都进行编写的话,会有很多重复性的代码。如果业务逻辑变更,这时候就要四处进行修改了。使用工厂模式进行统一的创建,就修改工厂类即可,降低成本难。

「简单工厂模式」

这种模式对对象的创建管理方式很简单,因为就是简单的对不同类的对象进行了一层简单的封装,该模式通过向工厂传递类型所指定的创建对象。在《设计模式》这本书里,把简单工厂模式看成工厂方法模式的一种特例,两者是归为一类的。

「工厂方法模式」

工厂方法模式又称为工厂模式,是对简单工厂模式的进一步抽象化,好处就是可以让系统在不修改原来代码的情况下引进新的产品,就是满足了开闭原则。通过工厂的父类负责创建产品的公共接口,通过子类来确定所需要创建的类型。跟简单工厂来比的话,这种方法具有很多的可扩展性和复用性,同时也增强了代码的可读性。具体就是将类的实例化(具体产品的创建)延迟到工厂类里的子类(具体工厂)里去完成,子类来决定应该实例化哪一个类。

/**
 * 工厂方法
 */
public interface PayFactory {
    Pay getPay();
}
/**
 * 具体产品工厂
 */
public class AliPayFactory implements PayFactory {
    @Override
    public Pay getPay() {
        return new AliPay();
    }
}
/**
 * 抽象产品
 */
public interface Pay {
    /**
     * 统一下单
     */
    void unifiedorder();
}
/**
 * 具体产品
 */
public class AliPay implements Pay {
    @Override
    public void unifiedorder() {
        System.out.println("支付宝支付 统一下单接口");
    }
}

以上这种工厂方法模式符合了开闭原则,因为没增加一个产品类,只需要实现其他具体产品类的具体工厂类。也符合了单一职责的原则,每一个工厂只负责生产相对应的产品,使用者只需要知道产品的抽象类,不用关系其他的实现类,满足了迪米特法则、依赖倒置原则和里氏替换原则。

迪米特法则:最少知道原则,实体应当尽量少地与其他实体之间发生相互作用

依赖倒置原则:针对接口编程,依赖于抽象而不依赖于具体

里氏替换原则:俗称LSP, 任何基类可以出现的地方,子类一定可以出现, 对实现抽象化的具体步骤的规范

工厂方法模式的缺点

在添加新的产品时候,需要重新编写新的具体产品类,并且还要提供与之相对应的具体工厂类,我们知道,在系统中类的个数将成对增加时,也在一定的程度上对系统的复杂度产生了变更,这时候就有更多的类需要编译和运行了,会给系统带来一些额外的开销。所以考虑到系统的可扩展性,需要引入抽象层,在客户端代码里均使用抽象层来定义,这样增加了系统的抽象性与理解难度,并且的话在实现时还可能需要用到DOM、反射等等的一些技术,增加系统的实现难度。

「抽象工厂模式」

工厂方法模式引入了工厂的等级结构,解决了简单工厂模式里的工厂类职责过重的问题,但是工厂方法模式中的每一个工厂都只创建一类具体类的对象,后续发展会导致工厂类变得越来越多,所以将一些相关的具体类组合成一个具体类组,由同一个工厂来统一生产,抢到的是一些列相关的产品对象。


实现步骤

1、定义两个接口 Pay、Refund

2、创建具体的Pay产品、创建具体的Refund产品

3、创建抽象工厂 OrderFactory 接口里面两个方法 createPay/createRefund

4、创建支付宝产品族AliOderFactory,实现OrderFactory抽象工厂

5、创建微信支付产品族WechatOderFactory,实现OrderFactory抽象工厂

6、定义一个超级工厂创造器,通过传递参数获取对应的工厂

/**
 * 超级工厂,定义同个产品族的其他相关子工厂
 */
public interface OrderFactory {
    PayFactory createPay();
    RefundFactory createRefund();
}
//产品族工厂的产品,可以不叫Factory,看公司团队规范,比如类名叫 IPay 也可以的
public interface PayFactory {
    /**
     * 统一下单
     */
    void unifiedorder();
}
//产品族工厂
public class AliOrderFactory implements OrderFactory {
    @Override
    public PayFactory createPay() {
        return new AliPay();
    }
    @Override
    public RefundFactory createRefund() {
        return new AliRefund();
    }
}
//具体产品
public class AliPay implements PayFactory {
    @Override
    public void unifiedorder() {
        System.out.println("支付宝支付 统一下单接口");
    }
}
//超级工厂生产器,传参生产对应的子工厂
public class FactoryProducer {
    public static OrderFactory getFactory(String type) {
        if (type.equalsIgnoreCase("WECHAT")) {
            return new WechatOrderFactory();
        } else if (type.equalsIgnoreCase("ALI")) {
            return new AliOrderFactory();
        }
        return null;
    }
}
//Main函数使用
OrderFactory orderFactory = FactoryProducer.getFactory("ALI");
orderFactory.createPay().unifiedorder();
orderFactory.createRefund().refund();

到了这里你会想问工厂方法模式与抽象工厂方法模式有什么区别呢?当抽象工厂模式中每一个具体的工厂类只能创建一个产品对象,抽象工厂模式退化成工厂方法模式。

「抽象工厂的优点」:抽象工厂模式隔离了具体类的生成,这就使得客户无需知道什么被创建了。就是因为这种隔离,更换一个具体工厂的话就会变得相对来说比较容易了。在所有的具体工厂都实现抽象工厂中定义了哪些公共接口,所以只需要改变具体工厂的实例,就可以说在某一种程度上改变了整一个软件系统的行为。还有就是抽象工厂模式可以实现高内聚低耦合的这种设计目的,所以抽象工厂模式得到了广泛的应用。增加新的具体工厂和产品族也方便,无需更改现有的系统,符合了开闭原则。

「抽象工厂的缺点」:在添加新的产品对象的时候,很难以扩展抽象工厂这种方式来生产新种类的产品,这是因为在抽象工厂角色里规定了所有可能被创建到的产品,要支持新的种类产品也就说明了要就接口来进行扩展,而这样将会涉及到对抽象工厂里的角色和子类的修改,这样显然就会带来不便。开闭原则的倾斜性(增加了新的工厂和产品容易,但是增加新的产品等级结构麻烦)

「那什么是开闭原则的倾斜性?」

我们知道开闭原则是要求系统对扩展具有开放性,对修改有封闭性。通过扩展可以达到对功能增强的目的。对于增强功能这一块会涉及到多个产品族与产品的等级结构,所以功能的增强包括了两个方面:

1、增加系统的产品族,对于添加新的产品族,工厂方法就很好的支持了开闭原则,对于新添加的产品族,就只需要相对应的添加一个具体工厂就可以了,不用对现有的代码做修改。

2、增加新的产品的等级结构,对于增加产品的等级结构,这就需要对所有的工厂角色进行修改,包括了抽象的工厂类,在所有的工厂类里面都需要添加生成新的产品方法,这就不是很符合了开闭原则

抽象工厂为新产品族提供了方便,但不可以为新产品的等级结构添加提供这样的方便

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。