设计模式-工厂方法

工厂方法(factory method)模式:稍微复杂一点的工厂模式

工厂方法模式,实际上就是:模板方法模式+简单工厂模式 的组合,认为就是简单工厂模式,稍微复杂一点的变种。

场景介绍:

(1) 我们现在要生产的产品有多种;

(2) 每种产品的生产过程,都有一些是共同的逻辑,但是也有一些是特殊的逻辑;

(3) 现在要生产出来各种产品

不用工厂方法模式的代码实现:

首先创建一个类,WithoutFactoryMethodPatternDemo 类,

public  class WithoutFactoryMethodPatternDemo{... }

因为我们要生产产品,所以,首先有一个 Product 接口,接口中有一个 execute方法,

public interface Product { void execute(); }

然后,假设我们有3中产品,第一个是静态的Product1,实现Product接口,及接口中的execute方法,其中输出 一句话,代表 产品1的功能逻辑,同样的,还有产品2 和产品3,现在相当于我们有这3种产品。

public static class Product1 implements Product{ public void execute(){ System.out.println("产品1的功能逻辑"); } }

然后的话,如果不用这个 工厂方法模式,我们就用 简单工厂模式 来做,声明一个静态的工厂类 Product1Factory,里面有一个静态的方法createProduct(),返回一个 Product1 的产品,并且它有两个逻辑,分别为 生产产品的通用逻辑 和 生产产品1的特殊逻辑。同样的,还有两个工厂 Product2Factory 和 Product3Factory,除通用逻辑外,也分别执行 生产产品2的特殊逻辑 和 生产产品3的特殊逻辑,并分别返回 Product2 和 Product3.

public static class Product1Factory { 
  public static Product createProduct(){ 
    System.out.println("生产产品的通用逻辑");
    System.out.println("生产产品1的特殊逻辑");
    return new Product1(); 
  } 
}

然后,我们在写个main方法,来玩一下。我们先调用Product1的工厂,执行Product1工厂中的execute方法,同样的,然后再是Product2,然后是Product3,

只用 简单工厂模式 的完整代码如下:

public class WithoutFactoryMethodPatternDemo {

    public static void main(String[] args) {
        Product product1 = Product1Factory.createProduct();
        Product product2 = Product2Factory.createProduct();
        Product product3 = Product3Factory.createProduct();

        product1.execute();
        product2.execute();
        product3.execute();
    }

    public interface Product {
        void execute();
    }

    public static class Product1 implements Product {
        @Override
        public void execute() {
            System.out.println("产品1的功能逻辑");
        }
    }

    public static class Product2 implements Product {
        @Override
        public void execute() {
            System.out.println("产品2的功能逻辑");
        }
    }

    public static class Product3 implements Product {
        @Override
        public void execute() {
            System.out.println("产品3的功能逻辑");
        }
    }

    public static class Product1Factory {
        public static Product createProduct() {
            System.out.println("生产产品的通用逻辑");
            System.out.println("生产产品1的特殊逻辑");
            return new Product1();
        }
    }

    public static class Product2Factory {
        public static Product createProduct() {
            System.out.println("生产产品的通用逻辑");
            System.out.println("生产产品2的特殊逻辑");
            return new Product2();
        }
    }

    public static class Product3Factory {
        public static Product createProduct() {
            System.out.println("生产产品的通用逻辑");
            System.out.println("生产产品3的特殊逻辑");
            return new Product3();
        }
    }
}

执行main方法,输出如下结果:首先是生产的一个过程,然后生产完了以后是 执行功能的一个过程。

生产产品的通用逻辑
生产产品1的特殊逻辑
生产产品的通用逻辑
生产产品2的特殊逻辑
生产产品的通用逻辑
生产产品3的特殊逻辑
产品1的功能逻辑
产品2的功能逻辑
产品3的功能逻辑

不用 工厂方法模式时 出现的问题

不用 工厂方法模式时,这个有一个什么问题,这个问题在于,其实就是跟那个模板方法模式的问题一模一样。就是多个工厂类中,有这个生产产品的,相同的这个通用逻辑,没有抽取出来,直接复制粘贴放多个工厂里了,如果那段通用逻辑要修改,就需要很麻烦,到所有工厂中去修改代码,可能会忘记修改某个工厂的代码,这样的话,那个工厂生产出来的产品就不符合要求。

比如,Product1Factory中的通用逻辑给它修改了,Product2Factory中的通用逻辑给它修改了,今天就是Product3Factory这给它忘了,那么程序再去跑起来,前面两个,生产产品1 和 生产产品2 的这个通用逻辑,都修改过了,生产产品3 的通用逻辑没有修改,那生产产品3,它就有bug了,所以说,这个肯定是不行的。

应用 工厂方法模式的代码实现:

那我们就来写一个 FactoryMethodPatternDemo,如果要用这个 工厂方法 设计模式的话,应该怎样写的,把没有用模式的实现 WithoutFactoryMethodPatternDemo,在它的基础之上来改,Product1,Product2 和 Product3,这3个产品,以及产品的接口 Product,是不用改变的,主要改的是产品工厂这边。

首先,它需要有 这么一个 静态的抽象工厂类 AbstractProductFactory,定义了 产品(即 继承此抽象类的每个子类) 的生产规范,

public static abstract calss AbstractProductFactory{... }

其中,主要有三个方法,

一个是private修饰的通用的逻辑方法,

private void commonCreate() {
  System.out.println("生产产品的通用逻辑");
}

一个是protected修饰的 未被实现特殊逻辑方法,

protected abstract Product specificCreate();

一个是public修饰的 整合 通用逻辑 和 特殊逻辑 生产出产品的逻辑方法,返回的是最终的产品对象,

public Product createProduct() {
  commonCreate();
  return specificCreate();
}

然后,所有的产品工厂类,分别继承于此产品工厂抽象类,并分别实现其中的特殊逻辑方法,比如,静态的工厂类 Product1Factory extends AbstractProductFactory,基于 简单工厂模式 Product1Factory 的代码:

public static class Product1Factory { 
  public static Product createProduct(){ 
    System.out.println("生产产品的通用逻辑");
    System.out.println("生产产品1的特殊逻辑");
    return new Product1(); 
  } 
}

1.Product1Factory 继承 AbstractProductFactory,并实现其中的 未被实现特殊逻辑方法 specificCreate(),因其在父类中无需供外部调用,所以是非static的;

2.将 简单工厂模式 Product1Factory 中的 createProduct 更名为 specificCreate,去掉static方法声明,去掉其中的通用逻辑,只实现生产产品的特殊逻辑,就可以了:

public static class Product1Factory extends AbstractProductFactory {

  public Product specificCreate(){
    System.out.println("生产产品1的特殊逻辑");
    return new Product1();
  }
}

3.最后,再把它 定义成一个简单的 单例形式,就是把每一个工厂,作为一个单个实例来用,用的是比较简单的单例模式:

声明一个static final的工厂Product1Factory引用,指向 一个 通过自身无参构造器new的实例,并通过 一个get方法,将此实例暴露出去,供外部接口调用此实例。

public static class Product1Factory extends AbstractProductFactory {

  private static final Product1Factory instance = new Product1Factory();

  private Product1Factory() {  }

  public static Product1Factory get() {
    return instance;
  }

  public Product specificCreate(){
    System.out.println("生产产品1的特殊逻辑");
    return new Product1();
  }
}

 同样的,还有两个工厂 Product2Factory 和 Product3Factory,都继承自 AbstractProductFactory,实现了特殊逻辑方法 specificCreate,分别执行了 生产产品2的特殊逻辑 和 生产产品3的特殊逻辑,并分别返回 Product2 和 Product3.

这样,我们就采用了 类似于模板方法的,这样的一个模式,这个 生产产品的通用逻辑 给它抽到了 一个抽象的工厂父类里面去,在工厂父类里面 放这个通用逻辑,然后,具体生产每个产品 的这个逻辑,交给每个 工厂子类 去实现,然后的话,每个工厂 给它实现成一个 简易的 单例的 这么一个方式。

然后再来看一下,那现在这个代码变成什么样子了。在main方法中,对比 只是用 简单工厂模式 的调用过程,使用 工厂方法模式,我们通过 单例模式 调用 产品工厂 去生产产品,再使用这个产品 调用execute方法 执行 产品的功能逻辑。

Product product1 = Product1Factory.get().createProduct();

同样的,还有 Product2 和 Product3,然后,我们分别执行一下它们的execut方法,输出一下结果,ok。

main方法,代码如下:

public static void main(String[] args) {
    /*
    Product product1 = Product1Factory.createProduct();
    Product product2 = Product2Factory.createProduct();
    Product product3 = Product3Factory.createProduct();

    product1.execute();
    product2.execute();
    product3.execute();
    */
    Product product1 = Product1Factory.get().createProduct();
    Product product2 = Product2Factory.get().createProduct();
    Product product3 = Product3Factory.get().createProduct();

    product1.execute();
    product2.execute();
    product3.execute();
}

使用 工厂方法模式 的完整代码如下:

public class FactoryMethodPatternDemo {

    public static void main(String[] args) {
        /*
        Product product1 = Product1Factory.createProduct();
        Product product2 = Product2Factory.createProduct();
        Product product3 = Product3Factory.createProduct();

        product1.execute();
        product2.execute();
        product3.execute();
        */
        Product product1 = Product1Factory.get().createProduct();
        Product product2 = Product2Factory.get().createProduct();
        Product product3 = Product3Factory.get().createProduct();

        product1.execute();
        product2.execute();
        product3.execute();
    }

    public interface Product {
        void execute();
    }

    public static class Product1 implements Product {
        @Override
        public void execute() {
            System.out.println("产品1的功能逻辑");
        }
    }

    public static class Product2 implements Product {
        @Override
        public void execute() {
            System.out.println("产品2的功能逻辑");
        }
    }

    public static class Product3 implements Product {
        @Override
        public void execute() {
            System.out.println("产品3的功能逻辑");
        }
    }

    public static abstract class AbstractProductFactory {

        public Product createProduct() {
            commonCreate();
            return specificCreate();

        }

        private void commonCreate() {
            System.out.println("生产产品的通用逻辑");
        }

        protected abstract Product specificCreate();
    }

    public static class Product1Factory extends AbstractProductFactory {

        private static final Product1Factory instance = new Product1Factory();

        private Product1Factory() {

        }

        public static Product1Factory get() {
            return instance;
        }

        public Product specificCreate() {
            System.out.println("生产产品1的特殊逻辑");
            return new Product1();
        }

    }

    public static class Product2Factory extends AbstractProductFactory{

        private static final Product2Factory instance = new Product2Factory();

        private Product2Factory() {

        }

        public static Product2Factory get() {
            return instance;
        }

        public Product specificCreate() {
            System.out.println("生产产品2的特殊逻辑");
            return new Product2();
        }
    }

    public static class Product3Factory extends AbstractProductFactory{

        private static final Product3Factory instance = new Product3Factory();

        private Product3Factory() {

        }

        public static Product3Factory get() {
            return instance;
        }

        public Product specificCreate() {
            System.out.println("生产产品3的特殊逻辑");
            return new Product3();
        }
    }
}

那我们来看一下,执行main方法,输出如下结果:生产产品的通用逻辑,特殊逻辑,执行这个功能,对吧!

生产产品的通用逻辑
生产产品1的特殊逻辑
生产产品的通用逻辑
生产产品2的特殊逻辑
生产产品的通用逻辑
生产产品3的特殊逻辑
产品1的功能逻辑
产品2的功能逻辑
产品3的功能逻辑

使用工厂方法模式的好处:

那使用 工厂方法模式,这个好处就是说,我们把每个工厂里面,生产产品的 一个通用逻辑 给抽到了一个,抽象的这个工厂里面来,比如说现在,我们要把生产产品的通用逻辑,把它给改一下,那么只修改一个地方就可以了。

private void commonCreate() {
  System.out.println("生产产品的通用逻辑,修改");
}

执行输出一下结果,如下:

生产产品的通用逻辑,修改
生产产品1的特殊逻辑
生产产品的通用逻辑,修改
生产产品2的特殊逻辑
生产产品的通用逻辑,修改
生产产品3的特殊逻辑
产品1的功能逻辑
产品2的功能逻辑
产品3的功能逻辑

那么,就不涉及到说,通用逻辑修改,要把每个工厂里面的代码,都要去修改,其实综上可以看到,这个就是把 简单工厂,跟那个 模板方法 给结合到了一起而已。

工厂方法模式的实际应用场景:

那么,这个模式实际上用的是比较少的,用的并不多,它针对的是说,对 工厂模式 做一个改良。那么我们实战 是在电商项目里面,结合后面的一个命令名模式,然后,再结合电商的一个业务,来演示说,这个 工厂方法 这个模式,跟 命令模式 结合在一起,然后,怎么去设计电商业务的这一块代码。

 

end

posted @ 2022-07-03 12:34  HarryVan  阅读(56)  评论(0)    收藏  举报