工厂模式

Posted yangxiaojie

tags:

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

老板:阿飞,上次面包店老板找我聊了一下,他们是大规模的从各大小原料商铺进的原料,出现了好多偷工减料的情况,现在他们做大了,想自己开几个原料提供点,如果中国的顾客去买,发现原料用尽,就要去找中国原料提供点,拿原料,这个功能看看好不好实现,如果好实现,你就开始做吧!

项目组长阿飞:这个可以实现,我去操作吧

项目组长阿飞:小三,来需求了…………,听懂了吗?你应该知道怎么拓展代码。

阿三:嗯嗯,我知道,我去拓展一下

三天过后。。

阿三:飞哥,设计好了,你看下。

这个是一个地址描述类,主要是表明是哪个地区的,有什么不同,这个是可以拓展的

技术分享图片
 1  package com.abstractFactoryPattern.material.vo;
 2  
 3  /**
 4   * @program: designPattern
 5   * @description: 材料所在地
 6   * @author: Mr.Yang
 7   * @create: -- :
 8   **/
 9  public  class Address {
10     public String name=null;
11 }
View Code
 

这个是中国地址类,对Address做了一个拓展,可以重写父类方法或者赋值属性,将特殊业务拿到子类去处理,做了个小拓展。

技术分享图片
 1  package com.abstractFactoryPattern.material.vo;
 2  
 3  /**
 4   * @program: designPattern
 5   * @description: 代表了中国的材料源地址,将它与其他材料源实现一个共同的父类,方便接收与拓展
 6   * @author: Mr.Yang
 7   * @create: -- :
 8   **/
 9  public class ChineseAddress extends Address{
10 
11     public ChineseAddress(){
12         name="中国材料源";
13     }
14 }
View Code
 

新加坡地址类,也是一样的。

技术分享图片
 1  package com.abstractFactoryPattern.material.vo;
 2  
 3  /**
 4   * @program: designPattern
 5   * @description: 代表了新加坡的材料源地址,将它与其他材料源实现一个共同的父类,方便接收与拓展
 6   * @author: Mr.Yang
 7   * @create: -- :
 8   **/
 9  public class SignaporeAddress extends Address{
10 
11     public SignaporeAddress(){
12         name="新加坡材料源";
13     }
14 
15 }
View Code

 

 

泰国的亦是如此

技术分享图片
 1  package com.abstractFactoryPattern.material.vo;
 2  
 3  /**
 4   * @program: designPattern
 5   * @description: 代表了泰国的材料源地址,将它与其他材料源实现一个共同的父类,方便接收与拓展
 6   * @author: Mr.Yang
 7   * @create: -- :
 8   **/
 9  public class ThailandAddress extends Address{
10 
11     public ThailandAddress(){
12         name="泰国材料源";
13     }
14 
15 }
View Code

 

 

这是一个材料工程的一个接口类,各大地方具体材料必须实现这个接口类

技术分享图片
 1  package com.abstractFactoryPattern.material.factory;
 2  
 3  import com.abstractFactoryPattern.material.vo.Address;
 4  
 5  /**
 6   * @program: designPattern
 7   * @description: 材料工程
 8   * @author: Mr.Yang
 9   * @create: -- :
10  **/
11 public interface  MaterialFactory {
12     /**
13      * 创建材料方法
14      * @return
15      */
16      Address selectAddress();
17 
18 
19 }
View Code

 

 

中国的原料工程,实现了材料工程的接口类,返回了一个中国的地址类

技术分享图片
 1  package com.abstractFactoryPattern.material.factoryImpl;
 2  
 3  import com.abstractFactoryPattern.material.factory.MaterialFactory;
 4  import com.abstractFactoryPattern.material.vo.Address;
 5  import com.abstractFactoryPattern.material.vo.ChineseAddress;
 6  
 7  /**
 8   * @program: designPattern
 9   * @description: 中国的原材料工程
10  * @author: Mr.Yang
11  * @create: -- :
12  **/
13 public class ChineseMaterialFactory implements MaterialFactory {
14 
15     @Override
16     public Address selectAddress() {
17         return new ChineseAddress();
18     }
19 }
View Code

 

 

新加坡的原料工程,实现了材料工程的接口类,返回了一个新加坡的地址类

技术分享图片
 1 package com.abstractFactoryPattern.material.factoryImpl;
 2  
 3  import com.abstractFactoryPattern.material.factory.MaterialFactory;
 4  import com.abstractFactoryPattern.material.vo.Address;
 5  import com.abstractFactoryPattern.material.vo.SignaporeAddress;
 6  
 7  /**
 8   * @program: designPattern
 9   * @description: 新加坡的原材料工程
10  * @author: Mr.Yang
11  * @create: -- :
12  **/
13 public class SingaporeMaterialFactory implements MaterialFactory {
14     @Override
15     public Address selectAddress() {
16         return new SignaporeAddress();
17     }
18 }
View Code

 

 

泰国的原料工程,实现了材料工程的接口类,返回了一个泰国的地址类

技术分享图片
 1  package com.abstractFactoryPattern.material.factoryImpl;
 2  
 3  import com.abstractFactoryPattern.material.factory.MaterialFactory;
 4  import com.abstractFactoryPattern.material.vo.Address;
 5  import com.abstractFactoryPattern.material.vo.ThailandAddress;
 6  
 7  /**
 8   * @program: designPattern
 9   * @description: 泰国的原材料工程
10  * @author: Mr.Yang
11  * @create: -- :
12  **/
13 public class ThailandMaterialFactory implements MaterialFactory {
14 
15     @Override
16     public Address selectAddress() {
17         return new ThailandAddress();
18     }
19 }
View Code

 

 

面包店的抽象类,进行了微改动,接受了地址类,增加了,去选择地址这个抽象方法,也就意味着,所有实现这个面包工程的将要去实现这个方法

技术分享图片
 1  package com.abstractFactoryPattern.kind.factory;
 2  
 3  import com.abstractFactoryPattern.material.vo.Address;
 4  
 5  /**
 6   * @program: designPattern
 7   * @description: 面包口味的抽象类
 8   * @author: Mr.Yang
 9   * @create: -- :
10  **/
11 public abstract class BreadFactory {
12     protected String name;
13     protected String type;
14 
15     //新增地址类属性
16     public Address address;
17 
18     //新增抽象方法
19     protected abstract void toSelectAddress();
20 
21     public BreadFactory stir(){
22         System.out.println("搅拌");
23         return this;
24     }
25 
26     public BreadFactory rubbingRound(){
27         System.out.println("搓圆");
28         return this;
29     }
30 
31     public BreadFactory machining(){
32         System.out.println("加工");
33         return this;
34     }
35     public BreadFactory bake(){
36         System.out.println("烘烤");
37         return this;
38     }
39 
40     public String getName() {
41         return name;
42     }
43 
44     public BreadFactory setName(String name) {
45         this.name = name;
46         return this;
47     }
48 
49     public String getType() {
50         return type;
51     }
52 
53     public BreadFactory setType(String type) {
54         this.type = type;
55         return this;
56     }
57 }
View Code

 

 

中国苹果口味的面包,实现抽象方法,重新给父类的几个属性赋值

技术分享图片
 1  package com.abstractFactoryPattern.kind.factoryImpl;
 2  
 3  import com.abstractFactoryPattern.kind.factory.BreadFactory;
 4  import com.abstractFactoryPattern.material.factory.MaterialFactory;
 5  
 6  /**
 7   * @program: designPattern
 8   * @description: 中国苹果口味面包
 9   * @author: Mr.Yang
10  * @create: -- :
11  **/
12 public class ChinaAppleBread  extends BreadFactory {
13     MaterialFactory materialFactory;
14 
15     //使用这个有参构造,去为属性赋值
16     public ChinaAppleBread(MaterialFactory materialFactory){
17         name="中国苹果口味";
18         type="";
19         this.materialFactory=materialFactory;
20         toSelectAddress();
21     }
22 
23     @Override
24     protected void toSelectAddress() {
25         address = materialFactory.selectAddress();
26     }
27 
28     //可以重写父类方法,进行特殊处理
29 }
View Code
 

中国奶油口味的面包,实现抽象方法,重新给父类的几个属性赋值

技术分享图片
 1 package com.abstractFactoryPattern.kind.factoryImpl;
 2  
 3  import com.abstractFactoryPattern.kind.factory.BreadFactory;
 4  import com.abstractFactoryPattern.material.factory.MaterialFactory;
 5  
 6  /**
 7   * @program: designPattern
 8   * @description: 中国奶油口味面包
 9   * @author: Mr.Yang
10  * @create: -- :
11  **/
12 public class ChinaCreamBread extends BreadFactory {
13     MaterialFactory materialFactory;
14 
15     public ChinaCreamBread(MaterialFactory materialFactory){
16         this.materialFactory=materialFactory;
17         name="中国奶油口味";
18         type="";
19         toSelectAddress();
20     }
21 
22     @Override
23     protected void toSelectAddress() {
24         address = materialFactory.selectAddress();
25     }
26     //可以重写父类方法,进行特殊处理
27 }
View Code
 

新加坡苹果口味的面包,实现抽象方法,重新给父类的几个属性赋值

技术分享图片
 1  package com.abstractFactoryPattern.kind.factoryImpl;
 2  
 3  import com.abstractFactoryPattern.kind.factory.BreadFactory;
 4  import com.abstractFactoryPattern.material.factory.MaterialFactory;
 5  
 6  /**
 7   * @program: designPattern
 8   * @description: 新加坡苹果口味面包
 9   * @author: Mr.Yang
10  * @create: -- :
11  **/
12 public class SingaporeAppleBread extends BreadFactory {
13     MaterialFactory materialFactory;
14 
15     public SingaporeAppleBread(MaterialFactory materialFactory){
16         this.materialFactory=materialFactory;
17         name="新加坡苹果口味";
18         type="";
19         toSelectAddress();
20     }
21 
22     @Override
23     protected void toSelectAddress() {
24         address = materialFactory.selectAddress();
25     }
26     //可以重写父类方法,进行特殊处理
27 }
View Code

 

 

新加坡奶油口味的面包,实现抽象方法,重新给父类的几个属性赋值

技术分享图片
 1  package com.abstractFactoryPattern.kind.factoryImpl;
 2  
 3  import com.abstractFactoryPattern.kind.factory.BreadFactory;
 4  import com.abstractFactoryPattern.material.factory.MaterialFactory;
 5  
 6  /**
 7   * @program: designPattern
 8   * @description: 新加坡奶油口味面包
 9   * @author: Mr.Yang
10  * @create: -- :
11  **/
12 public class SingaporeCreamBread extends BreadFactory {
13     MaterialFactory materialFactory;
14 
15     public SingaporeCreamBread(MaterialFactory materialFactory){
16         this.materialFactory=materialFactory;
17         name="新加坡奶油口味";
18         type="";
19         toSelectAddress();
20     }
21 
22     @Override
23     protected void toSelectAddress() {
24         address = materialFactory.selectAddress();
25     }
26     //可以重写父类方法,进行特殊处理
27 }
View Code

 

 

面包商店抽象类

技术分享图片
 1 package com.abstractFactoryPattern.breadStore.factory;
 2  
 3  import com.abstractFactoryPattern.kind.factory.BreadFactory;
 4  
 5  /**
 6   * @program: designPattern
 7   * @description: 面包商店抽象类
 8   * @author: Mr.Yang
 9   * @create: -- :
10  **/
11 public abstract class BreadStoreFactory {
12 
13     public BreadFactory orderBread(String type) {
14 
15         BreadFactory bread = createBread(type);
16         //做业务判断,如果材料耗尽,去拿材料
17         if(==){
18             System.out.println("材料耗尽");
19             System.out.println(bread.address.name+"_拿到材料");
20         }
21 
22         return   bread.stir()
23                 .rubbingRound()
24                 .machining()
25                 .bake();
26 
27     }
28 
29     public abstract BreadFactory createBread(String type);
30 }
View Code

 

 

中国店铺子类,将材料原材料工程,传递给BreadFactory的子类对象,再到构造方法

技术分享图片
 1  package com.abstractFactoryPattern.breadStore.factoryImpl;
 2  
 3  import com.abstractFactoryPattern.breadStore.factory.BreadStoreFactory;
 4  import com.abstractFactoryPattern.kind.factory.BreadFactory;
 5  import com.abstractFactoryPattern.kind.factoryImpl.ChinaAppleBread;
 6  import com.abstractFactoryPattern.kind.factoryImpl.ChinaCreamBread;
 7  import com.abstractFactoryPattern.material.factoryImpl.ChineseMaterialFactory;
 8  import com.abstractFactoryPattern.material.factory.MaterialFactory;
 9  
10 /**
11  * @program: designPattern
12  * @description: 中国店铺子类
13  * @author: Mr.Yang
14  * @create: -- :
15  **/
16 public class ChinaStore extends BreadStoreFactory {
17     @Override
18     public BreadFactory createBread(String type) {
19         BreadFactory breadFactory=null;
20         MaterialFactory chineseMaterialFactory = new ChineseMaterialFactory();
21         if("cream".equalsIgnoreCase(type)){
22             System.out.println("创建中国奶油口味面包");
23             breadFactory=new ChinaCreamBread(chineseMaterialFactory);
24         }else if("apple".equalsIgnoreCase(type)){
25             System.out.println("创建中国苹果口味面包");
26             breadFactory=new ChinaAppleBread(chineseMaterialFactory);
27         }else{
28             System.out.println("无法确认的面包类型");
29             return null;
30         }
31         return breadFactory;
32     }
33 }
View Code

 

 

新加坡店铺子类,将材料原材料工程,传递给BreadFactory的子类对象,再到构造方法

技术分享图片
 1  package com.abstractFactoryPattern.breadStore.factoryImpl;
 2  
 3  import com.abstractFactoryPattern.breadStore.factory.BreadStoreFactory;
 4  import com.abstractFactoryPattern.kind.factory.BreadFactory;
 5  import com.abstractFactoryPattern.kind.factoryImpl.SingaporeAppleBread;
 6  import com.abstractFactoryPattern.kind.factoryImpl.SingaporeCreamBread;
 7  import com.abstractFactoryPattern.material.factory.MaterialFactory;
 8  import com.abstractFactoryPattern.material.factoryImpl.SingaporeMaterialFactory;
 9  
10 /**
11  * @program: designPattern
12  * @description: 新加坡店铺子类
13  * @author: Mr.Yang
14  * @create: -- :
15  **/
16 public class SingaporeStore extends BreadStoreFactory {
17     @Override
18     public BreadFactory createBread(String type) {
19         BreadFactory breadFactory=null;
20         MaterialFactory singaporeMaterialFactory = new SingaporeMaterialFactory();
21         if("cream".equalsIgnoreCase(type)){
22             System.out.println("创建新加坡奶油口味面包");
23             breadFactory=new SingaporeCreamBread(singaporeMaterialFactory);
24         }else if("apple".equalsIgnoreCase(type)){
25             System.out.println("创建新加坡苹果口味面包");
26             breadFactory=new SingaporeAppleBread(singaporeMaterialFactory);
27         }else{
28             System.out.println("无法确认的面包类型");
29             return null;
30         }
31         return breadFactory;
32     }
33 }
View Code

 

 

泰国店铺子类,将材料原材料工程,传递给BreadFactory的子类对象,再到构造方法

技术分享图片
 1  package com.abstractFactoryPattern.breadStore.factoryImpl;
 2  
 3  import com.abstractFactoryPattern.breadStore.factory.BreadStoreFactory;
 4  import com.abstractFactoryPattern.kind.factory.BreadFactory;
 5  import com.abstractFactoryPattern.kind.factoryImpl.ThailandAppleBread;
 6  import com.abstractFactoryPattern.material.factory.MaterialFactory;
 7  import com.abstractFactoryPattern.material.factoryImpl.ThailandMaterialFactory;
 8  
 9  /**
10  * @program: designPattern
11  * @description: 泰国店铺子类
12  * @author: Mr.Yang
13  * @create: -- :
14  **/
15 public class ThailandStore extends BreadStoreFactory {
16     @Override
17     public BreadFactory createBread(String type) {
18         BreadFactory breadFactory=null;
19         MaterialFactory thailandMaterialFactory = new ThailandMaterialFactory();
20         if("cream".equalsIgnoreCase(type)){
21             System.out.println("创建泰国奶油口味面包");
22             breadFactory=new ThailandAppleBread(thailandMaterialFactory);
23         }else if("apple".equalsIgnoreCase(type)){
24             System.out.println("创建泰国苹果口味面包");
25             breadFactory=new ThailandAppleBread(thailandMaterialFactory);
26         }else{
27             System.out.println("无法确认的面包类型");
28             return null;
29         }
30         return breadFactory;
31     }
32 }
View Code

 

 

测试

技术分享图片
 1  package com.abstractFactoryPattern.patternTest;
 2  
 3  import com.abstractFactoryPattern.breadStore.factory.BreadStoreFactory;
 4  import com.abstractFactoryPattern.breadStore.factoryImpl.ChinaStore;
 5  
 6  /**
 7   * @program: designPattern
 8   * @description: 测试类
 9   * @author: Mr.Yang
10  * @create: -- :
11  **/
12 public class Test {
13     public static void main(String[] args) {
14         System.out.println("中国顾客买苹果味道面包");
15         BreadStoreFactory chinaBreadStoreFactory = new ChinaStore();
16         chinaBreadStoreFactory.orderBread("apple");
17     }
18 }
View Code

 

 

测试结果

技术分享图片
1 中国顾客买苹果味道面包
2 创建中国苹果口味面包
3 材料耗尽
4 中国材料源_拿到材料
5 搅拌
6 搓圆
7 加工
8 烘烤
View Code

 

 

阿三:这里我使用了抽象工厂模式,提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体的类。他允许了调用方,创建一个相关的产品,但是不需要知道具体的产品是什么。从具体的产品中解耦,这个是材料源与商店,地址的关系图

 

技术分享图片

 

项目组长阿飞:是的,抽象工厂经常以工厂方法的方式实现,抽象工厂的任务是定义一个负责创建一组产品的接口(材料提供点),接口内的每个方法都负责创建一个具体的产品(比如创建地址)。然后利用实现抽象工厂的子类来提供这些具体的做法

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

设计模式学习——简单工厂模式工厂模式抽象工厂模式

设计模式简单工厂模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )

设计模式学习——简单工厂模式工厂模式抽象工厂模式

设计模式工厂方法模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )

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

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