工厂方法模式

Posted gdwkong

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了工厂方法模式相关的知识,希望对你有一定的参考价值。

1 工厂模式介绍

  1.1 定义:定义一个用于创建对象的接口,让子类绝对实例化哪一个类,工厂方法使一个类的实例化延迟到其子类。

  工厂方法模式通用类图:

  在工厂模式中,抽象产品类Product负责定义产品的共性,实现对事物最抽象的定义,Creator为抽象类创建类,也就是抽象工厂,具体如何创建产品类是有具体的实现工厂ConcreteCreator完成的。

  1.2 工厂方法模式的优点

  • 良好的封装性,代码结构清晰。
  • 扩展性非常优秀,在增加产品类的情况系下,只有适当的修改具体的工厂类或扩展一个工厂类,就可以“拥抱变化”。
  • 屏蔽产品类。产品类的实现如何变化,调用者无需关心,它只需关心产品的接口,只要接口保持不变,系统中的上层模块就不需要发生变化。
  • 解耦框架。高层模块只需要知道产品的抽象类,其他实现类都不用关心。

  1.3 工厂方法模式的使用场景

2 工厂模式实现

2.1 简单工厂模式(静态工厂模式)

  以实现一个计算器为例:

  整个过程涉及到三个对象,人(Program4类表示)、计算器(以OperationFactory类表示)、计算方式(计算方式中有多种,加减乘除等,但都属于计算方法,以一个父类Operation,加减乘除继承覆写方法即可)。整个示例类如下图:

 1 public class Program4 {
 2     public static void main(String[] args) {
 3         try {
 4             Scanner scanner = new Scanner (System.in);
 5 
 6             System.out.println ("请输入数字A:");
 7             double numberA = Double.parseDouble (scanner.nextLine ());
 8             System.out.println ("选择运算符(+、-、*、/):");
 9             String strOperate = scanner.nextLine ();
10             System.out.println ("请输入数字B:");
11             double numberB = Double.parseDouble (scanner.nextLine ());
12             String strResult = "";
13 
14             if ( strOperate != "/" || numberB != 0){
15                 Operation oper;
16                 oper = OperationFactory.createOperate (strOperate);
17                 oper.setNumberA (numberA);
18                 oper.setNumberB (numberB);
19                 
20                 strResult = String.valueOf (oper.getResult ());
21                 System.out.println ("结果为:"+strResult);
22 
23             }else {
24                 System.out.println ("除数不能为零");
25             }
26 
27             scanner.close ();
28         } catch (Exception e) {
29             throw new RuntimeException("您输入有误:"+e.getMessage ());
30         }
31     }
32 }

 计算器(工厂)根据用户需求,选择(生成)符合需要的计算方式创建对应的实例对象,创建过程中需要需用户参与。

 1 public class OperationFactory {
 2     public static Operation createOperate(String operate) {
 3         Operation oper = null;
 4         switch (operate){
 5             case "+":
 6                 oper = new OperationAdd ();
 7                 break;
 8             case "-":
 9                 oper = new OperationSub ();
10                 break;
11             case "*":
12                 oper = new OperationMul ();
13                 break;
14             case "/":
15                 oper = new OperationDiv ();
16                 break;
17         }
18         return oper;
19     }
20 }
 1 public class Operation{
 2     private double numberA = 0;
 3     private double numberB = 0;
 4 
 5     public double getNumberA() { return numberA; }
 6 
 7     public void setNumberA(double numberA) { this.numberA = numberA; }
 8 
 9     public double getNumberB() { return numberB; }
10 
11     public void setNumberB(double numberB) { this.numberB = numberB; }
12 
13     public double getResult(){ 
14         double result = 0;
15         return result;
16     }
17 }
18 
19 class OperationAdd extends Operation{
20     @Override
21     public double getResult() {
22         double result = 0;
23         result = getNumberA () + getNumberB ();
24         return result;
25     }
26 }
27 
28 class OperationSub extends Operation{
29     @Override
30     public double getResult() {
31         double result = 0;
32         result = getNumberA () - getNumberB ();
33         return result;
34     }
35 }
36 
37 class OperationMul extends Operation{
38     @Override
39     public double getResult() {
40         double result = 0;
41         result = getNumberA () * getNumberB ();
42         return result;
43     }
44 }
45 
46 class OperationDiv extends Operation{
47     @Override
48     public double getResult() {
49         double result = 0;
50         result = getNumberA () / getNumberB ();
51         return result;
52     }
53 }

 简单工厂的缺点,不符合“开放封闭原则,要增加新的功能(计算方式)时,需要去修改工厂类(增加分支)。

2.2 多方法模式

是对普通工厂方法模式的改进,在普通工厂方法模式中,如果传递的字符串出错,则不能正确创建对象,而多个工厂方法模式是提供多个工厂方法,分别创建对象。

 1 public class OperationFactory03 {
 2 
 3     public Operation add(){
 4         return new OperationAdd();
 5     }
 6 
 7     public Operation sub(){
 8         return new OperationSub ();
 9     }
10 
11     public Operation mul(){
12         return new OperationMul();
13     }
14 
15     public Operation div(){
16         return new OperationDiv();
17     }
18 }
 1 public class FactoryTest {
 2 
 3     public static void main(String[] args) {
 4 
 5         OperationFactory03 factory03 = new OperationFactory03();
 6         Operation add = factory03.add();
 7         
 8         add.setNumberA(20);
 9         add.setNumberB(10);
10         double result = add.getResult();
11         System.out.println(result);
12     }
13 }

2.3 静态工厂方法模式

多个工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即可。

 1 public class OperationFactory {
 2 
 3     public static Operation add(){
 4         return new OperationAdd();
 5     }
 6 
 7     public static Operation sub(){
 8         return new OperationSub ();
 9     }
10 
11     public static Operation mul(){
12         return new OperationMul();
13     }
14 
15     public static Operation div(){
16         return new OperationDiv();
17     }
18 }
 1 //调用类
 2 public class FactoryTest {
 3 
 4     public static void main(String[] args) {
 5 
 6         Operation add = OperationFactory02.add();
 7         add.setNumberA(20);
 8         add.setNumberB(10);
 9         double result = add.getResult();
10         System.out.println(result);
11         
12     }
13 }

  总体来说,工厂模式适合:凡是出现了大量的产品需要创建,并且具有共同的接口时,可以通过工厂方法模式进行创建。在以上的三种模式中,第一种如果传 入的字符串有误,不能正确创建对象,第三种相对于第二种,不需要实例化工厂类,所以,大多数情况下,我们会选用第三种——静态工厂方法模式。

3  抽象工厂模式

  工厂方法模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改,这违背了闭包原则,所以,从设计角度考虑, 有一定的问题,如何解决?就用到抽象工厂模式,创建多个工厂类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。因为抽象 工厂不太好理解,我们先看看图,然后就和代码,就比较容易理解。

接口类

1 public interface Sender {
2     public void Send();
3 }

两个实现类

1 public class MsgSender implements Sender{
2 
3     @Override
4     public void Send() {
5         System.out.println("this is msgsender");
6     }
7 }
1 public class MailSender implements Sender {
2 
3     @Override
4     public void Send() {
5         System.out.println("this is mailsender!");
6     }
7 }

两个工厂类

1 public class SendmsgFactory implements Provider {
2 
3     @Override
4     public Sender produce() {
5         return new MsgSender();
6     }
7 }
1 public class SendmailFactory implements Provider {
2 
3     @Override
4     public Sender produce() {
5         return new MailSender();
6     }
7 }

提供一个接口

1 public interface Provider {
2     public Sender produce();
3 }

测试类

1 public class FactoryTest {
2     public static void main(String[] args) {
3         Provider provider = new SendmailFactory();
4         Sender sender = provider.produce();
5         sender.Send();
6     }
7 }

  其实这个模式的好处就是,如果你现在想增加一个功能:发及时信息,则只需做一个实现类,实现Sender接口,同时做一个工厂类,实现Provider接口,就OK了,无需去改动现成的代码。这样做,拓展性较好,即依赖抽象不依赖具体原则的体现。

以上是关于工厂方法模式的主要内容,如果未能解决你的问题,请参考以下文章

设计模式-简单工厂工厂方法模式抽象工厂模式详解

工厂方法模式

设计模式-工厂方法模式(Go实现)

C++工厂模式(简单工厂工厂方法抽象工厂)

C++工厂模式(简单工厂工厂方法抽象工厂)

设计模式---工厂模式