老板:阿飞,上次面包店老板找我聊了一下,他们是大规模的从各大小原料商铺进的原料,出现了好多偷工减料的情况,现在他们做大了,想自己开几个原料提供点,如果中国的顾客去买,发现原料用尽,就要去找中国原料提供点,拿原料,这个功能看看好不好实现,如果好实现,你就开始做吧!
项目组长阿飞:这个可以实现,我去操作吧
项目组长阿飞:小三,来需求了…………,听懂了吗?你应该知道怎么拓展代码。
阿三:嗯嗯,我知道,我去拓展一下
三天过后。。
阿三:飞哥,设计好了,你看下。
这个是一个地址描述类,主要是表明是哪个地区的,有什么不同,这个是可以拓展的
1package com.abstractFactoryPattern.material.vo;
2
3/**
4 * @program: designPattern
5 * @description: 材料所在地
6 * @author: Mr.Yang
7 * @create: 2018-11-20 21:24
8 **/
9public class Address {
10 public String name=null;
11}
这个是中国地址类,对Address做了一个拓展,可以重写父类方法或者赋值属性,将特殊业务拿到子类去处理,做了个小拓展。
1package com.abstractFactoryPattern.material.vo;
2
3/**
4 * @program: designPattern
5 * @description: 代表了中国的材料源地址,将它与其他材料源实现一个共同的父类,方便接收与拓展
6 * @author: Mr.Yang
7 * @create: 2018-11-20 21:24
8 **/
9public class ChineseAddress extends Address{
10
11 public ChineseAddress(){
12 name="中国材料源";
13 }
14}
新加坡地址类,也是一样的。
1package com.abstractFactoryPattern.material.vo;
2
3/**
4 * @program: designPattern
5 * @description: 代表了新加坡的材料源地址,将它与其他材料源实现一个共同的父类,方便接收与拓展
6 * @author: Mr.Yang
7 * @create: 2018-11-20 21:24
8 **/
9public class SignaporeAddress extends Address{
10
11 public SignaporeAddress(){
12 name="新加坡材料源";
13 }
14
15}
泰国的亦是如此
1package com.abstractFactoryPattern.material.vo;
2
3/**
4 * @program: designPattern
5 * @description: 代表了泰国的材料源地址,将它与其他材料源实现一个共同的父类,方便接收与拓展
6 * @author: Mr.Yang
7 * @create: 2018-11-20 21:25
8 **/
9public class ThailandAddress extends Address{
10
11 public ThailandAddress(){
12 name="泰国材料源";
13 }
14
15}
这是一个材料工程的一个接口类,各大地方具体材料必须实现这个接口类
1package com.abstractFactoryPattern.material.factory;
2
3import com.abstractFactoryPattern.material.vo.Address;
4
5/**
6 * @program: designPattern
7 * @description: 材料工程
8 * @author: Mr.Yang
9 * @create: 2018-11-20 20:58
10 **/
11public interface MaterialFactory {
12 /**
13 * 创建材料方法
14 * @return
15 */
16 Address selectAddress();
17
18
19}
中国的原料工程,实现了材料工程的接口类,返回了一个中国的地址类
1package com.abstractFactoryPattern.material.factoryImpl;
2
3import com.abstractFactoryPattern.material.factory.MaterialFactory;
4import com.abstractFactoryPattern.material.vo.Address;
5import com.abstractFactoryPattern.material.vo.ChineseAddress;
6
7/**
8 * @program: designPattern
9 * @description: 中国的原材料工程
10 * @author: Mr.Yang
11 * @create: 2018-11-20 21:10
12 **/
13public class ChineseMaterialFactory implements MaterialFactory {
14
15 @Override
16 public Address selectAddress() {
17 return new ChineseAddress();
18 }
19}
新加坡的原料工程,实现了材料工程的接口类,返回了一个新加坡的地址类
1package com.abstractFactoryPattern.material.factoryImpl;
2
3import com.abstractFactoryPattern.material.factory.MaterialFactory;
4import com.abstractFactoryPattern.material.vo.Address;
5import com.abstractFactoryPattern.material.vo.SignaporeAddress;
6
7/**
8 * @program: designPattern
9 * @description: 新加坡的原材料工程
10 * @author: Mr.Yang
11 * @create: 2018-11-20 21:11
12 **/
13public class SingaporeMaterialFactory implements MaterialFactory {
14 @Override
15 public Address selectAddress() {
16 return new SignaporeAddress();
17 }
18}
泰国的原料工程,实现了材料工程的接口类,返回了一个泰国的地址类
1package com.abstractFactoryPattern.material.factoryImpl;
2
3import com.abstractFactoryPattern.material.factory.MaterialFactory;
4import com.abstractFactoryPattern.material.vo.Address;
5import com.abstractFactoryPattern.material.vo.ThailandAddress;
6
7/**
8 * @program: designPattern
9 * @description: 泰国的原材料工程
10 * @author: Mr.Yang
11 * @create: 2018-11-20 21:12
12 **/
13public class ThailandMaterialFactory implements MaterialFactory {
14
15 @Override
16 public Address selectAddress() {
17 return new ThailandAddress();
18 }
19}
面包店的抽象类,进行了微改动,接受了地址类,增加了,去选择地址这个抽象方法,也就意味着,所有实现这个面包工程的将要去实现这个方法
1package com.abstractFactoryPattern.kind.factory;
2
3import com.abstractFactoryPattern.material.vo.Address;
4
5/**
6 * @program: designPattern
7 * @description: 面包口味的抽象类
8 * @author: Mr.Yang
9 * @create: 2018-11-18 19:24
10 **/
11public 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}
中国苹果口味的面包,实现抽象方法,重新给父类的几个属性赋值
1package com.abstractFactoryPattern.kind.factoryImpl;
2
3import com.abstractFactoryPattern.kind.factory.BreadFactory;
4import com.abstractFactoryPattern.material.factory.MaterialFactory;
5
6/**
7 * @program: designPattern
8 * @description: 中国苹果口味面包
9 * @author: Mr.Yang
10 * @create: 2018-11-18 19:48
11 **/
12public class ChinaAppleBread extends BreadFactory {
13 MaterialFactory materialFactory;
14
15 //使用这个有参构造,去为属性赋值
16 public ChinaAppleBread(MaterialFactory materialFactory){
17 name="中国苹果口味";
18 type="1";
19 this.materialFactory=materialFactory;
20 toSelectAddress();
21 }
22
23 @Override
24 protected void toSelectAddress() {
25 address = materialFactory.selectAddress();
26 }
27
28 //可以重写父类方法,进行特殊处理
29}
中国奶油口味的面包,实现抽象方法,重新给父类的几个属性赋值
1package com.abstractFactoryPattern.kind.factoryImpl;
2
3import com.abstractFactoryPattern.kind.factory.BreadFactory;
4import com.abstractFactoryPattern.material.factory.MaterialFactory;
5
6/**
7 * @program: designPattern
8 * @description: 中国奶油口味面包
9 * @author: Mr.Yang
10 * @create: 2018-11-18 19:48
11 **/
12public class ChinaCreamBread extends BreadFactory {
13 MaterialFactory materialFactory;
14
15 public ChinaCreamBread(MaterialFactory materialFactory){
16 this.materialFactory=materialFactory;
17 name="中国奶油口味";
18 type="2";
19 toSelectAddress();
20 }
21
22 @Override
23 protected void toSelectAddress() {
24 address = materialFactory.selectAddress();
25 }
26 //可以重写父类方法,进行特殊处理
27}
新加坡苹果口味的面包,实现抽象方法,重新给父类的几个属性赋值
1package com.abstractFactoryPattern.kind.factoryImpl;
2
3import com.abstractFactoryPattern.kind.factory.BreadFactory;
4import com.abstractFactoryPattern.material.factory.MaterialFactory;
5
6/**
7 * @program: designPattern
8 * @description: 新加坡苹果口味面包
9 * @author: Mr.Yang
10 * @create: 2018-11-18 19:50
11 **/
12public class SingaporeAppleBread extends BreadFactory {
13 MaterialFactory materialFactory;
14
15 public SingaporeAppleBread(MaterialFactory materialFactory){
16 this.materialFactory=materialFactory;
17 name="新加坡苹果口味";
18 type="3";
19 toSelectAddress();
20 }
21
22 @Override
23 protected void toSelectAddress() {
24 address = materialFactory.selectAddress();
25 }
26 //可以重写父类方法,进行特殊处理
27}
新加坡奶油口味的面包,实现抽象方法,重新给父类的几个属性赋值
1package com.abstractFactoryPattern.kind.factoryImpl;
2
3import com.abstractFactoryPattern.kind.factory.BreadFactory;
4import com.abstractFactoryPattern.material.factory.MaterialFactory;
5
6/**
7 * @program: designPattern
8 * @description: 新加坡奶油口味面包
9 * @author: Mr.Yang
10 * @create: 2018-11-18 19:50
11 **/
12public class SingaporeCreamBread extends BreadFactory {
13 MaterialFactory materialFactory;
14
15 public SingaporeCreamBread(MaterialFactory materialFactory){
16 this.materialFactory=materialFactory;
17 name="新加坡奶油口味";
18 type="4";
19 toSelectAddress();
20 }
21
22 @Override
23 protected void toSelectAddress() {
24 address = materialFactory.selectAddress();
25 }
26 //可以重写父类方法,进行特殊处理
27}
面包商店抽象类
1package com.abstractFactoryPattern.breadStore.factory;
2
3import com.abstractFactoryPattern.kind.factory.BreadFactory;
4
5/**
6 * @program: designPattern
7 * @description: 面包商店抽象类
8 * @author: Mr.Yang
9 * @create: 2018-11-18 19:51
10 **/
11public abstract class BreadStoreFactory {
12
13 public BreadFactory orderBread(String type) {
14
15 BreadFactory bread = createBread(type);
16 //做业务判断,如果材料耗尽,去拿材料
17 if(1==1){
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}
中国店铺子类,将材料原材料工程,传递给BreadFactory的子类对象,再到构造方法
1package com.abstractFactoryPattern.breadStore.factoryImpl;
2
3import com.abstractFactoryPattern.breadStore.factory.BreadStoreFactory;
4import com.abstractFactoryPattern.kind.factory.BreadFactory;
5import com.abstractFactoryPattern.kind.factoryImpl.ChinaAppleBread;
6import com.abstractFactoryPattern.kind.factoryImpl.ChinaCreamBread;
7import com.abstractFactoryPattern.material.factoryImpl.ChineseMaterialFactory;
8import com.abstractFactoryPattern.material.factory.MaterialFactory;
9
10/**
11 * @program: designPattern
12 * @description: 中国店铺子类
13 * @author: Mr.Yang
14 * @create: 2018-11-18 19:55
15 **/
16public 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}
新加坡店铺子类,将材料原材料工程,传递给BreadFactory的子类对象,再到构造方法
1package com.abstractFactoryPattern.breadStore.factoryImpl;
2
3import com.abstractFactoryPattern.breadStore.factory.BreadStoreFactory;
4import com.abstractFactoryPattern.kind.factory.BreadFactory;
5import com.abstractFactoryPattern.kind.factoryImpl.SingaporeAppleBread;
6import com.abstractFactoryPattern.kind.factoryImpl.SingaporeCreamBread;
7import com.abstractFactoryPattern.material.factory.MaterialFactory;
8import com.abstractFactoryPattern.material.factoryImpl.SingaporeMaterialFactory;
9
10/**
11 * @program: designPattern
12 * @description: 新加坡店铺子类
13 * @author: Mr.Yang
14 * @create: 2018-11-18 19:56
15 **/
16public 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}
泰国店铺子类,将材料原材料工程,传递给BreadFactory的子类对象,再到构造方法
1package com.abstractFactoryPattern.breadStore.factoryImpl;
2
3import com.abstractFactoryPattern.breadStore.factory.BreadStoreFactory;
4import com.abstractFactoryPattern.kind.factory.BreadFactory;
5import com.abstractFactoryPattern.kind.factoryImpl.ThailandAppleBread;
6import com.abstractFactoryPattern.material.factory.MaterialFactory;
7import com.abstractFactoryPattern.material.factoryImpl.ThailandMaterialFactory;
8
9/**
10 * @program: designPattern
11 * @description: 泰国店铺子类
12 * @author: Mr.Yang
13 * @create: 2018-11-18 19:56
14 **/
15public 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}
测试
1package com.abstractFactoryPattern.patternTest;
2
3import com.abstractFactoryPattern.breadStore.factory.BreadStoreFactory;
4import com.abstractFactoryPattern.breadStore.factoryImpl.ChinaStore;
5
6/**
7 * @program: designPattern
8 * @description: 测试类
9 * @author: Mr.Yang
10 * @create: 2018-11-18 20:13
11 **/
12public class Test {
13 public static void main(String[] args) {
14 System.out.println("中国顾客买苹果味道面包");
15 BreadStoreFactory chinaBreadStoreFactory = new ChinaStore();
16 chinaBreadStoreFactory.orderBread("apple");
17 }
18}
测试结果
1中国顾客买苹果味道面包
2创建中国苹果口味面包
3材料耗尽
4中国材料源_拿到材料
5搅拌
6搓圆
7加工
8烘烤
阿三:这里我使用了抽象工厂模式,提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体的类。他允许了调用方,创建一个相关的产品,但是不需要知道具体的产品是什么。从具体的产品中解耦,这个是材料源与商店,地址的关系图
项目组长阿飞:是的,抽象工厂经常以工厂方法的方式实现,抽象工厂的任务是定义一个负责创建一组产品的接口(材料提供点),接口内的每个方法都负责创建一个具体的产品(比如创建地址)。然后利用实现抽象工厂的子类来提供这些具体的做法