zoukankan      html  css  js  c++  java
  • `设计模式之工厂模式

      最近在学习设计模式的路上越走越远...

      今天主要记录记录一下学习的工厂模式。

       工厂模式简历

      1、由来    

      当我们创建一个对象,而这个对象的创建过程序纷繁复杂,可能导致大量的重复代码的时候,工厂模式出现了。工厂方法模式通过定义一个单独的创建对象的方法来解决这些问题。由子类实现这个方法来创建具体类型的对象。也就是说,在我们的实际运用中,工厂就是一个用来创建其他对象的对象。

      2、实质

      定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行。

      3、现状介绍

      工厂模式目前有三个分支,简单工厂模式,工厂方法模式和抽象工厂方法模式,其中,我主要学习的是抽象工厂方法模式,因为该方法是工厂模式中最高层的方法。简单工厂模式,工厂类根据传参不同得到不同的产品。工厂方法模式能够创建这个系列中的各种产品,比如,iphone的各种配件。而抽象工厂模式作为更高级的模式,它可以创建整个苹果公司各个产品流水线,比如,他可以创建生产iphone配件的工厂,可以创建生产ipad配件的工厂等等。那么,抽象工厂模式与工厂方法模式的最大区别就在于,工厂方法模式针对的是一个产品等级结构,它能够创建这一个等级结构中的产品族;而抽象工厂模式则需要面对多个产品等级结构,也就是说,抽象工厂方法模式可以工厂方法模式中的工厂。

      4、三分支的关系

      简单工厂模式通常伴随着对象的具体类型与工厂具体类型的一一对应,客户端代码根据需要选择合适的具体类型工厂使用。当这个选择包含复杂的逻辑时,就可以创建一个单一的工厂类,用以包含这种选择逻辑,根据参数的不同选择实现不同的具体对象。这个工厂类不需要由每个具体产品实现一个自己的具体的工厂类,所以可以将工厂方法设置为静态方法,这就有了工厂方法模式。而抽象工厂方法模式便是封装着这样一组有着共同主题的工厂方法模式中的工厂。

      

       三分支的应用场景

      1、简单工厂模式

      当我们的主程序中需要自己手动初始化一个对象,但是我们并不想关注具体的初始化过程,这个时候简单工厂模式就是您的选择。

      2、工厂方法模式

      当你觉得传入参数的这种简单的工厂模式让你程序容易出错,并且程序中的if-else让你的程序看起来有些臃肿,这个时候工厂方法模式就是您的选择。

      3、抽象工厂方法模式

      当你工厂类需要修改时,而在工厂方法模式中需要修改原有的工厂类,这就违背了设计原则中的OCP(开放闭合原则),这个时候,抽象工厂方法模式就是您的选择。 

       实际应用

      说不如做,看的再多不自己亲手做一做来的有效率,这便是我学习工厂模式之后的心得。

      首先,模拟场景。创建宝马车,X6和5系的,那么首先的有一个抽象的汽车工厂,CarFactory,由它来生成X6和5系的工厂,一个汽车工厂生产出来的汽车至少得有个壳,发动机,变速箱啥的,所有就有了方法。创建CarFactory如下:

    1 public interface CarFactory {
    2     public CarFrame createCarFrame();
    3     public Engine createEngine();
    4     public Gearbox createGearbox();
    5 }

    一个汽车的基本配件都出来了,那么所有的配件都应该有各自的接口,我们再分别创建Engine,Gearbox和CarFrame,Engine如下(Gearbox、CarFrame类似):

    1 public interface Engine {
    2     public void createEngine();
    3 
    4 }

    然后我们的X6和5系的都应该有这些个接口吧,我们在分别创建他们各自的Engine,Gearbox和CarFrame,X6的Engine:

     1 public class BwmXSixEngine implements Engine {
     2 
     3     private String emissions;
     4 
     5     public BwmXSixEngine(String emissions){
     6 
     7         this.emissions = emissions;
     8     }
     9 
    10     @Override
    11     public void createEngine() {
    12         System.out.println("this BWM XDrive engine,and emissions is "+ this.emissions);
    13     }
    14 }

    5系的Engine:

     1 public class BwmFiveSeriesEngine implements Engine {
     2 
     3     private final String emissions;
     4 
     5     public BwmFiveSeriesEngine(String emissions){
     6         this.emissions = emissions;
     7     }
     8 
     9     @Override
    10     public void createEngine() {
    11         System.out.println("this is BWMFiveSeriesEngine it's emissions of "+this.emissions);
    12     }
    13 }

    现在,X6和5系就只差装箱,我们就来创建他们的工厂吧,5系:

     1 public class BwmFiveSeriesFactory implements CarFactory{
     2 
     3 
     4     @Override
     5     public CarFrame createCarFrame() {
     6         return new BwmFiveSeriesCarFrame("中大型车", new int[]{5047,1860,1491},"4门5座三厢车");
     7     }
     8 
     9     @Override
    10     public Engine createEngine() {
    11         return new BwmFiveSeriesEngine("2.0T");
    12     }
    13 
    14     @Override
    15     public Gearbox createGearbox() {
    16         return new BwmFIveSeriesGearbox("8挡手自一体");
    17     }
    18 }

    X6:

     1 public class BwmXSixFactory implements CarFactory {
     2     @Override
     3     public CarFrame createCarFrame() {
     4         return new BwmXSixCarFrame("中大型SUV",new int[]{4929,1983,1709},"5门5座SUV");
     5     }
     6 
     7     @Override
     8     public Engine createEngine() {
     9         return new BwmXSixEngine("3.0T");
    10     }
    11 
    12     @Override
    13     public Gearbox createGearbox() {
    14         return new BwmXSixGearbox("8挡手自一体");
    15     }
    16 }

    程序写到这里也快结束了,我们自己在写一个汽车超市来生成这些对象就好了,希望你有一次愉快的购物经历,哈哈~

       总结

      在抽象工厂模式的运用中,需要有一个总的抽象工厂,这个工厂制造可以生产具体东西的工厂类,比如,CarFactory和BwmXSixFactory之间的关系。然后就是接口的运用。接口对于高抽象层级的类有很大作用,站在高处便能规定对继承该接口的类的行为,但并不具体到每一个继承的类的行为。最后,工厂模式成功的隐藏了类的行为,满足迪米特法则,调用者根本不关心怎么实现的,只要一个接口可以调用便行。

      自己在设计模式这一块还比较弱,以后还需多多学习。设计模式每一个都不是太难,重要的是各个击破之后,将他们拿捏在手中能够灵活的运用到实例的工作中。所以,重要的还是自己能力的提升,加油~

    ps:文中若是有哪里理解不顺或是需要改进的地方,望指出~

  • 相关阅读:
    AtCoder AGC036C GP 2 (组合计数)
    Luogu P4708 画画 (Burnside引理、组合计数、划分数)
    BZOJ 1488 Luogu P4727 [HNOI2009]图的同构 (Burnside引理、组合计数)
    BZOJ 2655 calc (组合计数、DP、多项式、拉格朗日插值)
    POJ 1430 Binary Stirling Numbers (第二类斯特林数、组合计数)
    BZOJ 4555 Luogu P4091 [HEOI2016/TJOI2016]求和 (第二类斯特林数)
    Luogu P4707 重返现世 (拓展Min-Max容斥、DP)
    LOJ #6358 前夕 (组合计数、容斥原理)
    BZOJ 3622 Luogu P4859 已经没有什么好害怕的了 (容斥原理、DP)
    Java基本的程序结构设计 大数操作
  • 原文地址:https://www.cnblogs.com/wfsovereign/p/4359760.html
Copyright © 2011-2022 走看看