设计模式-工厂方法

工厂方法(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的特殊逻辑。同样的,还有两个工厂 Product2FactoryProduct3Factory,除通用逻辑外,也分别执行 生产产品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,在它的基础之上来改,Product1Product2Product3,这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的特殊逻辑,并分别返回 Product2Product3.

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

然后再来看一下,那现在这个代码变成什么样子了。在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  阅读(26)  评论(0编辑  收藏  举报