工厂模式
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 }
这个是中国地址类,对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 }
新加坡地址类,也是一样的。
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 }
泰国的亦是如此
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 }
这是一个材料工程的一个接口类,各大地方具体材料必须实现这个接口类
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 }
中国的原料工程,实现了材料工程的接口类,返回了一个中国的地址类
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 }
新加坡的原料工程,实现了材料工程的接口类,返回了一个新加坡的地址类
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 }
泰国的原料工程,实现了材料工程的接口类,返回了一个泰国的地址类
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 }
面包店的抽象类,进行了微改动,接受了地址类,增加了,去选择地址这个抽象方法,也就意味着,所有实现这个面包工程的将要去实现这个方法
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 }
中国苹果口味的面包,实现抽象方法,重新给父类的几个属性赋值
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 }
中国奶油口味的面包,实现抽象方法,重新给父类的几个属性赋值
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 }
新加坡苹果口味的面包,实现抽象方法,重新给父类的几个属性赋值
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 }
新加坡奶油口味的面包,实现抽象方法,重新给父类的几个属性赋值
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 }
面包商店抽象类
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 }
中国店铺子类,将材料原材料工程,传递给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 }
新加坡店铺子类,将材料原材料工程,传递给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 }
泰国店铺子类,将材料原材料工程,传递给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 }
测试
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 }
测试结果
1 中国顾客买苹果味道面包 2 创建中国苹果口味面包 3 材料耗尽 4 中国材料源_拿到材料 5 搅拌 6 搓圆 7 加工 8 烘烤
阿三:这里我使用了抽象工厂模式,提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体的类。他允许了调用方,创建一个相关的产品,但是不需要知道具体的产品是什么。从具体的产品中解耦,这个是材料源与商店,地址的关系图
项目组长阿飞:是的,抽象工厂经常以工厂方法的方式实现,抽象工厂的任务是定义一个负责创建一组产品的接口(材料提供点),接口内的每个方法都负责创建一个具体的产品(比如创建地址)。然后利用实现抽象工厂的子类来提供这些具体的做法
以上是关于工厂模式的主要内容,如果未能解决你的问题,请参考以下文章
设计模式简单工厂模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )