楼子湾

导航

统计
 

本文转载自:https://www.cnblogs.com/gdwkong/p/8413342.html,原文是将工厂方法模式和抽象工厂模式放在一起了好做比较,我这里拆分开

1.工厂模式介绍

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

  工厂方法的通用类图

  

 

 

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

  1.2工厂方法模式的有点

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

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

 2.简单工厂模式的实现

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

  以实现一个计算器为例:

  整个过程设计三个对象:人(Program4表示),计算器(以OperationFactory表示),计算方式(计算方式有多种,加减乘除等,都属于计算方法,以一个父类Operation,加减乘除继承覆写方法即

  可)。整个示例类如下:

  

 

 

 

 1 public class Program4 {
 2 
 3     public static void main(String[] args) {
 4         Scanner scanner = new Scanner(System.in);
 5         System.out.println("请输入数字A");
 6         double numberA = Double.parseDouble(scanner.nextLine());
 7         System.out.println ("选择运算符(+、-、*、/):");
 8         String atrithmeticType = scanner.nextLine();
 9         System.out.println("请输入数字B");
10         double numberB = Double.parseDouble(scanner.nextLine());
11         Operation operate = OperationFactory.createOperate(atrithmeticType);
12 
13         if (atrithmeticType.equals("/") && numberB == 0){
14             System.out.println("除数不能为0");
15         }else {
16             operate.setNumberA(numberA);
17             operate.setNumberB(numberB);
18             double result = operate.result();
19             System.out.println("结果为:1" + result);
20         }
21         scanner.close();
22     }
23 }

  计算器(工程)用户需求,选择(生产)符合需要的计算方式创建对应的示例对象,创建过程需要用户参与。

  

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

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

2.2多方法工厂模式

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

 1 public class OperationFactory03 {
 2     public Operation add(){
 3         return new OperationAdd();
 4     }
 5     public Operation sub(){
 6         return new OperationSub();
 7     }
 8     public Operation mul(){
 9         return new OperationMul();
10     }
11     public Operation div(){
12         return new OperationDiv();
13     }
14 }
15 
16 
17 // main方法中
18 OperationFactory03 operationFactory03 = new OperationFactory03();
19         Operation add = operationFactory03.add();
20         add.setNumberA(1);
21         add.setNumberB(2);
22         double result = add.result();
23         System.out.println("结果是:" + result);

2.3静态工厂方法

多个工厂方法设置为静态,不需要创建工厂,直接创建对象

 1 public class OperationFactory04 {
 2     public static Operation add(){
 3         return new OperationAdd();
 4     }
 5     public static Operation sub(){
 6         return new OperationSub();
 7     }
 8     public static Operation mul(){
 9         return new OperationMul();
10     }
11     public static Operation div(){
12         return new OperationDiv();
13     }
14 }
15 
16 // main方法中
17 Operation add = OperationFactory04.add();
18         add.setNumberA(1);
19         add.setNumberB(2);
20         double result = add.result();
21         System.out.println("结果是:" + result);

总体来说:工厂模式,适合出现了大量产品需要创建,并且具有共同的接口时,可以通过工厂方法模式进行创建。

在以上三种工程方法模式中,第一种如果不能正确的传入字符,不能正确创建对象;第三种相对于第二种不需要实例化工厂,所以大多数情况下我们会选择第三种--------静态工厂方法模式。

3.工厂方法模式

一个抽象类可以派生出多个具体的产品类,主要针对某一类产品

  3.1工厂方法模式分为个角色:

  Product:抽象产品类

  ConcreteProduct:具体的产品类

  Creator:抽象的工厂类

  ConcreteCreator:具体的工厂类

  3.2应用

  这里就不和原文一样了,就用通用 例子来演示:冰箱

  冰箱有很多品牌:海尔 格力 小米 

 

 

 

 

 

 

 1 public class Market {
 2     public static void main(String[] args) {
 3         System.out.println("商场跟工厂说我要海尔冰箱10台, 美的冰箱2台, 小米冰箱2台");
 4         Factory hairFridgeFactory = new HairFridgeFactory();
 5         // 工厂生产 海尔
 6         Fridge hairFridge = hairFridgeFactory.createFridge();
 7         hairFridge.info();
 8         // 工厂生产 美的
 9         Factory mediFridgeFactory = new MediFridgeFactory();
10         Fridge mediFridge = mediFridgeFactory.createFridge();
11         mediFridge.info();
12         // 工厂生产 小米
13         Factory miFridgeFactory = new MiFridgeFactory();
14         Fridge miFridge = miFridgeFactory.createFridge();
15         miFridge.info();
16     }
17 }
18 
19 /**
20  * 抽象工厂类
21  */
22 public abstract class Factory {
23 
24     /**
25      *  创建冰箱类
26      * @param
27      * @return
28      */
29     public abstract Fridge createFridge();
30 }
31 /**
32  * 抽象冰箱类
33  */
34 public abstract class Fridge {
35     public abstract void info();
36 }
37 
38 public class HairFridgeFactory extends Factory {
39     @Override
40     public Fridge createFridge() {
41         return new HairFridge();
42     }
43 }
44 
45 public class MediFridgeFactory extends Factory {
46     @Override
47     public Fridge createFridge() {
48         return new MediFridge();
49     }
50 }
51 
52 public class MiFridgeFactory extends Factory {
53     @Override
54     public Fridge createFridge() {
55         return new MediFridge();
56     }
57 }
58 
59 public class HairFridge extends Fridge {
60     @Override
61     public void info() {
62         System.out.println("美的冰箱");
63     }
64 }
65 
66 
67 public class MediFridge extends Fridge {
68     @Override
69     public void info() {
70         System.out.println("美的冰箱");
71     }
72 }
73 
74 public class MiFridge extends Fridge {
75     @Override
76     public void info() {
77         System.out.println("小米冰箱");
78     }
79 }

 

从上面的代码可以看出这里遵循了开闭原则,单一原则,同时这里发现如果我想增加冰箱品牌,我直接扩展一个冰箱的实现类和一个冰箱的工厂类

优点:

在工厂方法中,客户端只需要知道所要产品的具体工厂,无需关心具体的创建过程,甚至不需要具体产品的类名。

增加新的产品时,只需要添加一个具体产品类和对应的实现工厂,无需对原工厂进行任何修改,符合开-闭原则。

缺点:

每增加一个产品时,都需要增加一个具体类和实现工厂,导致系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖 。

  

posted on 2020-03-09 13:51  楼子湾  阅读(...)  评论(...编辑  收藏