老板:阿飞啊,我们公司最近接了个项目,你看着设计一下,我给你说下需求。
项目组长阿飞:好啊,什么需求?
老板:我们找了一个合作的商铺,他们要设计一套面包销售系统。主要功能,根据用户选择的面包种类来下订单,面包目前有奶油口味面包和苹果口味面包,所有面包的制作流程都是---搅拌,搓圆,加工,烘烤。
项目组长阿飞:好的,我去想想怎么设计。
项目组长阿飞:小三啊,我给你个任务,…………,听懂了吗?
阿三:听懂了,飞哥。
项目组长阿飞:嗯嗯,好的,这个任务就交给你了,我要去处理点事情,我相信你。
阿三:。。。
三天过后。
阿三:飞哥,设计好了,你看下。
1 package com.factoryPattern.factory; 2 3 /** 4 * @program: designPattern 5 * @description: 面包口味的抽象类 6 * @author: Mr.Yang 7 * @create: 2018-11-18 19:24 8 **/ 9 public abstract class BreadFactory { 10 protected String name; 11 protected String type; 12 13 public BreadFactory stir(){ 14 System.out.println("搅拌"); 15 return this; 16 } 17 18 public BreadFactory rubbingRound(){ 19 System.out.println("搓圆"); 20 return this; 21 } 22 23 public BreadFactory machining(){ 24 System.out.println("加工"); 25 return this; 26 } 27 public BreadFactory bake(){ 28 System.out.println("烘烤"); 29 return this; 30 } 31 32 public String getName() { 33 return name; 34 } 35 36 public BreadFactory setName(String name) { 37 this.name = name; 38 return this; 39 } 40 41 public String getType() { 42 return type; 43 } 44 45 public BreadFactory setType(String type) { 46 this.type = type; 47 return this; 48 } 49 }
现在已有的两种口味继承这个抽象类--奶油面包
package com.factoryPattern.breadKind;import com.factoryPattern.breadKind.factory.BreadFactory;/*** @program: designPattern* @description: 奶油味面包* @author: Mr.Yang* @create:**/ public class CreamBread extends BreadFactory {public CreamBread(){name="奶油味";type="2";}//可以重写父类方法,进行特殊处理 }
苹果味面包
1 package com.factoryPattern.breadKind; 2 3 import com.factoryPattern.breadKind.factory.BreadFactory; 4 5 /** 6 * @program: designPattern 7 * @description: 苹果味面包 8 * @author: Mr.Yang 9 * @create: 10 **/ 11 public class AppleBread extends BreadFactory { 12 public AppleBread(){ 13 name="苹果味"; 14 type="1"; 15 } 16 //可以重写父类方法,进行特殊处理 17 }
然后是销售系统
1 package com.factoryPattern.breadKind.breadOrder; 2 3 import com.factoryPattern.breadKind.AppleBread; 4 import com.factoryPattern.breadKind.CreamBread; 5 import com.factoryPattern.breadKind.factory.BreadFactory; 6 7 /** 8 * @program: designPattern 9 * @description: 面包订单销售类 10 * @author: Mr.Yang 11 * @create: 12 **/ 13 public class BreadOrder { 14 15 16 BreadFactory orderBread(String type){ 17 BreadFactory breadFactory; 18 if("cream".equalsIgnoreCase(type)){ 19 System.out.println("创建奶油口味面包"); 20 breadFactory=new CreamBread(); 21 }else if("apple".equalsIgnoreCase(type)){ 22 System.out.println("创建苹果口味面包"); 23 breadFactory=new AppleBread(); 24 }else{ 25 System.out.println("无法确认的面包类型"); 26 return null; 27 } 28 29 return breadFactory.stir() 30 .rubbingRound() 31 .machining() 32 .bake(); 33 } 34 }
项目组长阿飞:三啊,不错,学会使用抽象了,但是如果我还要增加好几种面包类型呢?阿尔法面包销售不好,不想做这个了呢?之前给你说过设计模式的原则之一,对拓展开放,对修改关闭。如果有改动,可能会一直在这个代码的基础上累加做修改的。最好把创建对象的代码与销售的代码分隔开。
阿三:好的,我再修改修改(真的是,搞这么麻烦干嘛!)
又三天过后。
阿三:飞哥,修改好了,你看下。
新增了一个工程类
1 package com.factoryPattern.breadCreate; 2 3 import com.factoryPattern.breadKind.AppleBread; 4 import com.factoryPattern.breadKind.CreamBread; 5 import com.factoryPattern.breadKind.factory.BreadFactory; 6 7 /** 8 * @program: designPattern 9 * @description: 面包创建工程 10 * @author: Mr.Yang 11 * @create: 12 **/ 13 public class BreadCreateFactory { 14 public BreadFactory createBread(String type){ 15 BreadFactory breadFactory=null; 16 if("cream".equalsIgnoreCase(type)){ 17 System.out.println("创建奶油口味面包"); 18 breadFactory=new CreamBread(); 19 }else if("apple".equalsIgnoreCase(type)){ 20 System.out.println("创建苹果口味面包"); 21 breadFactory=new AppleBread(); 22 }else{ 23 System.out.println("无法确认的面包类型"); 24 return null; 25 } 26 return breadFactory; 27 } 28 }
修改了销售类
1 package com.factoryPattern.breadKind.breadOrder; 2 3 import com.factoryPattern.breadCreate.BreadCreateFactory; 4 import com.factoryPattern.breadKind.factory.BreadFactory; 5 6 /** 7 * @program: designPattern 8 * @description: 面包订单销售类 9 * @author: Mr.Yang 10 * @create: 11 **/ 12 public class BreadOrder { 13 BreadCreateFactory breadCreateFactory; 14 15 public BreadOrder(BreadCreateFactory breadCreateFactory) { 16 this.breadCreateFactory = breadCreateFactory; 17 } 18 19 BreadFactory orderBread(String type) { 20 return breadCreateFactory.createBread(type) 21 .stir() 22 .rubbingRound() 23 .machining() 24 .bake(); 25 } 26 }
项目组长阿飞:不错,这是一个简单工厂,但是你要记住,这并不是一个设计模式,而是一个编程习惯,一个不错的编程习惯,简单工厂把全部的事情,在一个地方处理完了,工厂方法是创建一个框架,让子类决定如何实现。还有领导说需求变了,这个面包店开了分店,一个在泰国,一个在新加坡,你看着再修改下吧,你可以考虑加入工厂方法。
阿三:好的(我服了,真的是****)
又三天过后。
阿三:飞哥,修改好了,这是完整代码,你看下。
先是一个面包商店抽象类
1 package com.factoryPattern.breadStore; 2 3 import com.factoryPattern.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 return createBread(type) 15 .stir() 16 .rubbingRound() 17 .machining() 18 .bake(); 19 } 20 21 abstract BreadFactory createBread(String type); 22 }
创建一个中国店铺子类实现商店抽象类
1 package com.factoryPattern.breadStore; 2 3 import com.factoryPattern.factory.BreadFactory; 4 import com.factoryPattern.kind.ChinaAppleBread; 5 import com.factoryPattern.kind.ChinaCreamBread; 6 7 /** 8 * @program: designPattern 9 * @description: 中国店铺子类 10 * @author: Mr.Yang 11 * @create: -- : 12 **/ 13 public class ChinaStore extends BreadStoreFactory{ 14 @Override 15 BreadFactory createBread(String type) { 16 BreadFactory breadFactory=null; 17 if("cream".equalsIgnoreCase(type)){ 18 System.out.println("创建中国奶油口味面包"); 19 breadFactory=new ChinaCreamBread(); 20 }else if("apple".equalsIgnoreCase(type)){ 21 System.out.println("创建中国苹果口味面包"); 22 breadFactory=new ChinaAppleBread(); 23 }else{ 24 System.out.println("无法确认的面包类型"); 25 return null; 26 } 27 return breadFactory; 28 } 29 }
创建一个新加坡店铺子类
1 package com.factoryPattern.breadStore; 2 3 import com.factoryPattern.factory.BreadFactory; 4 import com.factoryPattern.kind.SingaporeAppleBread; 5 import com.factoryPattern.kind.SingaporeCreamBread; 6 7 /** 8 * @program: designPattern 9 * @description: 新加坡店铺子类 10 * @author: Mr.Yang 11 * @create: -- : 12 **/ 13 public class SingaporeStore extends BreadStoreFactory { 14 @Override 15 BreadFactory createBread(String type) { 16 BreadFactory breadFactory=null; 17 if("cream".equalsIgnoreCase(type)){ 18 System.out.println("创建新加坡奶油口味面包"); 19 breadFactory=new SingaporeCreamBread(); 20 }else if("apple".equalsIgnoreCase(type)){ 21 System.out.println("创建新加坡苹果口味面包"); 22 breadFactory=new SingaporeAppleBread(); 23 }else{ 24 System.out.println("无法确认的面包类型"); 25 return null; 26 } 27 return breadFactory; 28 } 29 }
创建一个泰国店铺子类
1 package com.factoryPattern.breadStore; 2 3 import com.factoryPattern.factory.BreadFactory; 4 import com.factoryPattern.kind.ThailandAppleBread; 5 6 /** 7 * @program: designPattern 8 * @description: 泰国店铺子类 9 * @author: Mr.Yang 10 * @create: -- : 11 **/ 12 public class ThailandStore extends BreadStoreFactory { 13 @Override 14 BreadFactory createBread(String type) { 15 BreadFactory breadFactory=null; 16 if("cream".equalsIgnoreCase(type)){ 17 System.out.println("创建泰国奶油口味面包"); 18 breadFactory=new ThailandAppleBread(); 19 }else if("apple".equalsIgnoreCase(type)){ 20 System.out.println("创建泰国苹果口味面包"); 21 breadFactory=new ThailandAppleBread(); 22 }else{ 23 System.out.println("无法确认的面包类型"); 24 return null; 25 } 26 return breadFactory; 27 } 28 }
面包口味的抽象类
1 package com.factoryPattern.factory; 2 3 /** 4 * @program: designPattern 5 * @description: 面包口味的抽象类 6 * @author: Mr.Yang 7 * @create: -- : 8 **/ 9 public abstract class BreadFactory { 10 protected String name; 11 protected String type; 12 13 public BreadFactory stir(){ 14 System.out.println("搅拌"); 15 return this; 16 } 17 18 public BreadFactory rubbingRound(){ 19 System.out.println("搓圆"); 20 return this; 21 } 22 23 public BreadFactory machining(){ 24 System.out.println("加工"); 25 return this; 26 } 27 public BreadFactory bake(){ 28 System.out.println("烘烤"); 29 return this; 30 } 31 32 public String getName() { 33 return name; 34 } 35 36 public BreadFactory setName(String name) { 37 this.name = name; 38 return this; 39 } 40 41 public String getType() { 42 return type; 43 } 44 45 public BreadFactory setType(String type) { 46 this.type = type; 47 return this; 48 } 49 }
中国苹果口味面包
1 package com.factoryPattern.kind; 2 3 import com.factoryPattern.factory.BreadFactory; 4 5 /** 6 * @program: designPattern 7 * @description: 中国苹果口味面包 8 * @author: Mr.Yang 9 * @create: -- : 10 **/ 11 public class ChinaAppleBread extends BreadFactory { 12 public ChinaAppleBread(){ 13 name="中国苹果口味"; 14 type=""; 15 } 16 //可以重写父类方法,进行特殊处理 17 }
中国奶油口味面包
1 package com.factoryPattern.kind; 2 3 import com.factoryPattern.factory.BreadFactory; 4 5 /** 6 * @program: designPattern 7 * @description: 中国奶油口味面包 8 * @author: Mr.Yang 9 * @create: -- : 10 **/ 11 public class ChinaCreamBread extends BreadFactory { 12 public ChinaCreamBread(){ 13 name="中国奶油口味"; 14 type=""; 15 } 16 //可以重写父类方法,进行特殊处理
还有新加坡苹果口味面包,新加坡奶油口味面包,泰国苹果口味面包,泰国奶油口味面包
测试类
1 package com.factoryPattern.patternTest; 2 3 import com.factoryPattern.breadStore.BreadStoreFactory; 4 import com.factoryPattern.breadStore.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 烘烤
项目组长阿飞:看着不错,给我讲解一下吧。
阿三:我所用的是设计模式中的工厂模式,让子类决定该创建的对象是什么,来达到将对象创建的过程封装的目的。我简单的画了个图
阿三:大致如图,工程模式的定义:定义了一个创建对象的接口,但有子类决定要实例化的类是哪一个。工程方法让类把实例化推迟到子类
项目组长阿飞:很好,看来你已经掌握了工程模式的精髓,工程模式遵循了一个设计原则:“要依赖抽象,不要依赖具体实现。”,它有一个响亮的名字:“依赖倒置原则”。 你看你这两个图。创建者抽象BreadStoreFactory依赖与BreadFactory抽象类,面包的具体实现(chinaAppleBread,chinaCreamBread)依赖与BreadFactory抽象类,想要遵循依赖倒置原则,工程方法并非是唯一的,但是确是最有威力的技巧之一。
阿三:好的(我早就知道了---膨胀的一批)