工厂模式(Factory Pattern) 与抽象工厂模式(Abstract Factory Pattern)
工厂模式属于构造型模式,是项目中最常用到的一种设计模式。它的主要作用是提供一种简单的创建对象的方式,使用者无需知道创建实例的细节以及需要哪些资源,只要告诉工厂类指定名字即可,工厂类会在内部创建好该实例后返回给使用者。
工厂模式的使用
假设:现在程序中存在皮鞋、拖鞋、跑鞋三种鞋子,当我想得到一个鞋子对象时,需要进行设置鞋码,染色等过程。但是我在创建对象时,不希望通过很复杂的过程来 `new` 出来一个对象,我只想通过指定的鞋子类型就能得到一个创建好的鞋子对象,这个时候就需要一个工厂类来帮我创建一双鞋子对象了,所有的创建过程都在工厂类中实现,而我只需要调用工厂类的静态获取方法就能得到一个创建好的鞋子对象。
工厂模式类图
实现方法
第一步,创建鞋子的抽象父类
鞋
package 工厂模式.实体;
public abstract class 鞋 {
public Integer 鞋码;
public String 颜色;
public 鞋() {
}
public void 设置鞋码(Integer 鞋码) {
System.out.println("鞋子大小设置成功!");
this.鞋码 = 鞋码;
}
public void 染色(String 颜色) {
this.颜色 = 颜色;
System.out.println("鞋子染色成功!");
}
public abstract void 属性();
}
第二步,创建三种鞋子类
皮鞋
package 工厂模式.实体;
public class 皮鞋 extends 鞋 {
public 皮鞋(){
System.out.println("开始生产一双皮鞋……");
}
@Override
public void 属性() {
System.out.println("这是一双打工时穿的皮鞋,鞋码为"+this.鞋码+",颜色为"+this.颜色);
}
}
拖鞋
package 工厂模式.实体;
public class 拖鞋 extends 鞋 {
public 拖鞋(){
System.out.println("开始生产一双拖鞋……");
}
@Override
public void 属性() {
System.out.println("这是一双收租的时候穿的拖鞋,鞋码为"+this.鞋码+",颜色为"+this.颜色);
}
}
跑鞋
package 工厂模式.实体;
public class 跑鞋 extends 鞋 {
public 跑鞋(){
System.out.println("开始生产一双跑鞋……");
}
@Override
public void 属性() {
System.out.println("这是一双跑步时穿的跑鞋,鞋码为"+this.鞋码+",颜色为"+this.颜色);
}
}
第三步,创建工厂类
工厂类
package 工厂模式;
import 工厂模式.实体.拖鞋;
import 工厂模式.实体.皮鞋;
import 工厂模式.实体.跑鞋;
import 工厂模式.实体.鞋;
public class 工厂类 {
public static 鞋 获取一双鞋(String 鞋子类别名){
鞋 一双鞋子 = null;
// 通过使用者传来的字符串来判断工厂创建什么鞋子
switch (鞋子类别名){
case "皮鞋":
一双鞋子 = new 皮鞋();
break;
case "拖鞋":
一双鞋子 = new 拖鞋();
break;
case "跑鞋":
一双鞋子 = new 跑鞋();
break;
}
// 反正用户没指定什么鞋码和颜色,默认设置下鞋码与颜色
if (一双鞋子 != null){
一双鞋子.设置鞋码(42);
一双鞋子.染色("黑色");
}
// 工厂返回创建好的鞋子
return 一双鞋子;
}
}
第四步,创建测试类测试
测试类
package 工厂模式;
import 工厂模式.实体.鞋;
public class 测试类{
public static void main(String[] args) {
// 我想要一双皮鞋,于是通过工厂类获得皮鞋类的对象
鞋 皮鞋 = 工厂类.获取一双鞋("皮鞋");
皮鞋.属性();
// 我想要一双拖鞋,于是通过工厂类获得拖鞋类的对象
鞋 拖鞋 = 工厂类.获取一双鞋("拖鞋");
拖鞋.属性();
// 我想要一双跑鞋,于是通过工厂类获得跑鞋类的对象
鞋 跑鞋 = 工厂类.获取一双鞋("跑鞋");
跑鞋.属性();
}
}
测试结果
抽象工厂模式的使用
当工厂管理的类很少的时候,那么使用简单的工厂模式就可以了,因为一个工厂类即可完成所有工作。但是,当存在很多个类的创建需要受管理时,那么还使用一个工厂类就很臃肿了。
为解决一个工厂类过于臃肿的问题,我决定把多个类按它们的客观关联关系分配给多个工厂类来管理,而这些新的工厂类,我又要创建一个超级工厂类来管理这些工厂,并且为了方便超级工厂管理这些工厂类,这些工厂类需要继承一个抽象工厂类,从而使超级工厂操作他们的抽象类,而非具体类,符合依赖倒置原则。
假设:除了上文的鞋子,我现在还需要工厂管理卫衣、衬衫、毛衣,很明显他们都继承于衣服类,与鞋子不搭边。于是我不再用一个工厂管理他们,而是使用为鞋子工厂类和衣服工厂类分别管理,同时这些工厂类我也需要一个超级工厂来管理、
抽象工厂模式类图
实现方法
第一步,创建鞋子和衣服的抽象父类
鞋
package 设计模式.抽象工厂模式.实体;
public abstract class 鞋 {
public Integer 鞋码;
public String 颜色;
public void 设置鞋码(Integer 鞋码) {
System.out.println("鞋子大小设置成功!");
this.鞋码 = 鞋码;
}
public void 染色(String 颜色) {
this.颜色 = 颜色;
System.out.println("鞋子染色成功!");
}
public abstract void 属性();
}
衣服
package 设计模式.抽象工厂模式.实体;
public abstract class 衣服 {
public Integer 尺码;
public String 颜色;
public void 设置衣服大小(Integer 尺码) {
System.out.println("衣服大小裁剪成功!");
this.尺码 = 尺码;
}
public void 染色(String 颜色) {
this.颜色 = 颜色;
System.out.println("衣服染色成功!");
}
public abstract void 属性();
}
第二步,创建三种鞋子类和三种衣服类
皮鞋
package 设计模式.抽象工厂模式.实体;
public class 皮鞋 extends 鞋 {
public 皮鞋(){
System.out.println("开始生产一双皮鞋……");
}
@Override
public void 属性() {
System.out.println("这是一双打工时穿的皮鞋,鞋码为"+this.鞋码+",颜色为"+this.颜色);
}
}
跑鞋
package 设计模式.抽象工厂模式.实体;
public class 跑鞋 extends 鞋 {
public 跑鞋(){
System.out.println("开始生产一双跑鞋……");
}
@Override
public void 属性() {
System.out.println("这是一双跑步时穿的跑鞋,鞋码为"+this.鞋码+",颜色为"+this.颜色);
}
}
拖鞋
package 设计模式.抽象工厂模式.实体;
public class 拖鞋 extends 鞋 {
public 拖鞋(){
System.out.println("开始生产一双拖鞋……");
}
@Override
public void 属性() {
System.out.println("这是一双收租的时候穿的拖鞋,鞋码为"+this.鞋码+",颜色为"+this.颜色);
}
}
卫衣
package 设计模式.抽象工厂模式.实体;
public class 卫衣 extends 衣服{
public 卫衣() {
System.out.println("正在制作衣服……");
}
@Override
public void 属性() {
System.out.println("这是一件卫衣,尺码为"+this.尺码+",颜色为"+this.颜色);
}
}
衬衫
package 设计模式.抽象工厂模式.实体;
public class 衬衫 extends 衣服{
public 衬衫() {
System.out.println("正在制作衣服……");
}
@Override
public void 属性() {
System.out.println("这是一件衬衫,尺码为"+this.尺码+",颜色为"+this.颜色);
}
}
毛衣
package 设计模式.抽象工厂模式.实体;
public class 毛衣 extends 衣服{
public 毛衣() {
System.out.println("正在制作衣服……");
}
@Override
public void 属性() {
System.out.println("这是一件毛衣,尺码为"+this.尺码+",颜色为"+this.颜色);
}
}
第三步,创建具体工厂的抽象父类
抽象工厂
package 设计模式.抽象工厂模式.工厂;
import 设计模式.抽象工厂模式.实体.*;
public abstract class 抽象工厂 {
public abstract 鞋 获取一双鞋(String 鞋子类别名);
public abstract 衣服 获取一件衣服(String 衣服类别名);
}
第四步,创建鞋子工厂类和衣服工厂类
鞋子工厂
package 设计模式.抽象工厂模式.工厂;
import 设计模式.抽象工厂模式.实体.拖鞋;
import 设计模式.抽象工厂模式.实体.皮鞋;
import 设计模式.抽象工厂模式.实体.跑鞋;
import 设计模式.抽象工厂模式.实体.衣服;
import 设计模式.抽象工厂模式.实体.鞋;
public class 鞋子工厂 extends 抽象工厂 {
@Override
public 鞋 获取一双鞋(String 鞋子类别名) {
鞋 一双鞋子 = null;
// 通过使用者传来的字符串来判断工厂创建什么鞋子
switch (鞋子类别名){
case "皮鞋":
一双鞋子 = new 皮鞋();
break;
case "拖鞋":
一双鞋子 = new 拖鞋();
break;
case "跑鞋":
一双鞋子 = new 跑鞋();
break;
}
// 反正用户没指定什么鞋码和颜色,默认设置下鞋码与颜色
if (一双鞋子 != null){
一双鞋子.设置鞋码(42);
一双鞋子.染色("黑色");
}
// 工厂返回创建好的鞋子
return 一双鞋子;
}
@Override
public 衣服 获取一件衣服(String 衣服类别名) {
return null;
}
}
衣服工厂
package 设计模式.抽象工厂模式.工厂;
import 设计模式.抽象工厂模式.实体.*;
public class 衣服工厂 extends 抽象工厂 {
@Override
public 鞋 获取一双鞋(String 鞋子类别名) {
return null;
}
@Override
public 衣服 获取一件衣服(String 衣服类别名) {
衣服 一件衣服 = null;
// 通过使用者传来的字符串来判断工厂创建什么衣服
switch (衣服类别名){
case "卫衣":
一件衣服 = new 卫衣();
break;
case "衬衫":
一件衣服 = new 衬衫();
break;
case "毛衣":
一件衣服 = new 毛衣();
break;
}
// 默认设置下衣服大小与颜色
if (一件衣服 != null){
一件衣服.设置衣服大小(42);
一件衣服.染色("黑色");
}
// 工厂返回创建好的衣服
return 一件衣服;
}
}
第五步,创建超级工厂类
超级工厂类
package 设计模式.抽象工厂模式;
import 设计模式.抽象工厂模式.实体.拖鞋;
import 设计模式.抽象工厂模式.实体.皮鞋;
import 设计模式.抽象工厂模式.实体.跑鞋;
import 设计模式.抽象工厂模式.实体.鞋;
import 设计模式.抽象工厂模式.工厂.抽象工厂;
import 设计模式.抽象工厂模式.工厂.衣服工厂;
import 设计模式.抽象工厂模式.工厂.鞋子工厂;
public class 超级工厂类 {
public static 抽象工厂 获取指定工厂(String 工厂类别名){
抽象工厂 工厂 = null;
// 通过使用者传来的字符串来判断创建一个什么样的产品工厂
switch (工厂类别名){
case "xzgc":
工厂 = new 鞋子工厂();
break;
case "yfgc":
工厂 = new 衣服工厂();
break;
}
// 超级工厂返回创建好的产品工厂
return 工厂;
}
}
第六步,创建测试类测试
测试类
package 设计模式.抽象工厂模式;
import 设计模式.抽象工厂模式.实体.衣服;
import 设计模式.抽象工厂模式.实体.鞋;
import 设计模式.抽象工厂模式.工厂.抽象工厂;
public class 测试类{
public static void main(String[] args) {
// 通过超级工厂获得制作衣服的衣服工厂,yfgc是我自己指定的衣服工厂的类别名
抽象工厂 衣服工厂 = 超级工厂类.获取指定工厂("yfgc");
衣服 卫衣 = 衣服工厂.获取一件衣服("卫衣");
卫衣.属性();
衣服 衬衫 = 衣服工厂.获取一件衣服("衬衫");
衬衫.属性();
衣服 毛衣 = 衣服工厂.获取一件衣服("毛衣");
毛衣.属性();
System.out.println("————————————————————————————————————");
// 通过超级工厂获得制作鞋子的鞋子工厂,xzgc是我自己指定的鞋子工厂的类别名
抽象工厂 鞋子工厂 = 超级工厂类.获取指定工厂("xzgc");
// 我想要一双皮鞋,于是通过工厂类获得皮鞋类的对象
鞋 皮鞋 = 鞋子工厂.获取一双鞋("皮鞋");
皮鞋.属性();
// 我想要一双拖鞋,于是通过工厂类获得拖鞋类的对象
鞋 拖鞋 = 鞋子工厂.获取一双鞋("拖鞋");
拖鞋.属性();
// 我想要一双跑鞋,于是通过工厂类获得跑鞋类的对象
鞋 跑鞋 = 鞋子工厂.获取一双鞋("跑鞋");
跑鞋.属性();
}
}
测试结果