工厂模式是23种设计模式中比较基础的一种,其目的是隐藏了建立对象的细节,客户端与具体的实现类解耦,令客户端可以面向接口编程。数据库
从简单到复杂的场景,一共有三种模式。下面拿最多见的球衣做为例子讲解一下,若有不正确的地方请指正,图片和部分语言摘自网络,侵删。编程
假设如今有一个球衣的抽象类,有两个实现类,一个为足球球衣,另外一个为篮球球衣。代码以下:设计模式
1 abstract class Jersey { 2 abstract public void putOn(); 3 } 4 5 class FootballJersey extends Jersey{ 6 7 @Override 8 public void putOn() { 9 // TODO Auto-generated method stub 10 System.out.println("put on football jersey."); 11 } 12 13 } 14 15 class BasketballJersey extends Jersey { 16 17 @Override 18 public void putOn() { 19 // TODO Auto-generated method stub 20 System.out.println("put on basketball jersey."); 21 } 22 23 }
1. 简单工厂模式网络
如今客户端要使用一个足球球衣的对象,可能你第一个想到的,就是直接new一个对象。Jersey jersey = new FootballJersey();ide
这样一来,客户端就和球衣的实现类耦合了,一旦球衣的实现类发生变化,大量的实现类将让客户端的代码维护变得麻烦。函数
还有一种状况,在实际项目中,可能建立一个对象的时候,须要给它赋值,读取文件等,这些操做放在构造函数里会让对象的建立变得复杂,而若是让客户端自行设置,又可能出现代码重复或设置不正确的状况。这时,工厂类起到了一个隐藏实现细节的做用。学习
这是Head First 设计模式的理由:ui
简单工厂模式,就是实现一个工厂类,客户端根据须要,传入不一样的标识,获得一个实例。spa
1 class SimpleFactory{ 2 3 public static Jersey getJersey(int i) { 4 switch (i) { 5 case 1: 6 return new FootballJersey(); 7 8 case 2: 9 return new BasketballJersey(); 10 11 default: 12 return null; 13 } 14 } 15 }
客户端调用:设计
1 public static void main(String[] args) { 2 Jersey jersey = SimpleFactory.getJersey(1); 3 if (null != jersey) { 4 jersey.putOn(); 5 } 6 }
示例图,懒得画,网上随便找一个,你们意会
2. 工厂方法模式和抽象工厂模式
上面的代码
1)客户端在调用时可能并不知道须要传入什么样的标识。
2)当生产的产品类型增长的时候,必须修改工厂类的代码,这违背了开闭原则(对扩展开放,对修改关闭)。
3)当生产的产品类型增长的时候,工厂类的代码会很是臃肿,可能致使上帝类。
为了解决这个问题,工厂方法模式应运而生。它定义了一个抽象工厂类,产品不是由惟一的一个工厂类实现,而是由具体的子类来实现。
这样,在产品类型增长的时候,只须要继承抽象工厂类,实现一个具体的工厂,生产出对应的产品便可。对原来的工厂没有修改,却扩展了能力,同时释放了简单工厂类的压力。
对于客户端来讲,须要依赖一个具体的工厂对象。
仍以球衣为例子,定义一个球衣工厂的抽象类,篮球球衣和足球球衣由各自的工厂类生产。
1 abstract class JerseyFactory { 2 public abstract Jersey createJersey(); 3 } 4 5 class FootballJerseyFactory extends JerseyFactory { 6 7 @Override 8 public Jersey createJersey() { 9 return new FootballJersey(); 10 } 11 } 12 13 class BasketballJerseyFactory extends JerseyFactory { 14 15 @Override 16 public Jersey createJersey() { 17 return new BasketballJersey(); 18 } 19 }
客户端调用
1 public static void main(String[] args) { 2 JerseyFactory footballJerseyFactory = new FootballJerseyFactory(); 3 Jersey footballJersey = footballJerseyFactory.createJersey(); 4 footballJersey.putOn(); 5 }
此时,须要一件羽毛球球衣,并不须要修改原有的代码,而是实现一个羽毛球球衣工厂。
示例图:里面的ConcreteCreator就是具体的工厂类
3. 抽象工厂模式
抽象工厂模式是工厂方法模式的扩展版,用于生产一系列的产品。
在学习抽象工厂模式之类,先要理解两个概念:产品族和产品等级结构。
产品等级结构,能够理解为产品的继承结构。好比球衣和它的子类,足球衣,篮球衣,羽毛球衣一块儿构成了一个等级结构。球鞋和它的子类,足球鞋篮球鞋羽毛球鞋构造等级结构。
产品族,是指同一个工厂中生产的,位于不一样产品等级结构的一系列产品。
注意,是同一个工厂中生产的一系列产品,意味着一个工厂能够不仅生产一个产品。
产品位于不一样的等级结构,如球衣和球鞋,就是不一样的等级结构。
我我的认为,产品族能够理解为一个解决方案。为了解决一个实际的问题,从不一样的等级结构中选取合适的实例,组合成一个产品族。例如,足球衣和足球鞋,就是一个产品族。
经过引进抽象工厂模式,能够处理具备相同(或者类似)等级结构的多个产品族中的产品对象的建立问题。
当一个工厂等级结构能够建立出分属于不一样产品等级结构的一个产品族中的全部对象时,抽象工厂模式比工厂方法模式更为简单、更有效率。
从上面的图能够看出,各个产品等级结构之间能够自由组合,变幻出无穷的产品族。
一般,一个产品族内部的产品,都是有必定的联系的,好比足球衣和足球鞋。固然,你要是说就要足球衣配篮球鞋去踢球,那也是阔以的。
上面说了抽象工厂模式是工厂方法模式的扩展版,因此聪明的你从“同一个工厂中生产的一系列产品”能够得知,所谓扩展,就是工厂类会有多个生产不一样等级结构的产品的方法。
下面咱们增长球鞋抽象类,并实现足球鞋和篮球鞋。
1 abstract class Shoe { 2 public abstract void putOn(); 3 } 4 5 class FootballShoe extends Shoe { 6 7 @Override 8 public void putOn() { 9 System.out.println("put on football shoes."); 10 } 11 } 12 13 class BasketballShoe extends Shoe { 14 15 @Override 16 public void putOn() { 17 // TODO Auto-generated method stub 18 System.out.println("put on basketball shoes"); 19 } 20 21 }
定义抽象工厂类,能够生产多个不一样等级结构的产品。并实现两个工厂。
1 abstract class EquipmentFactory { 2 public abstract Jersey createJersey(); 3 public abstract Shoe createShoe(); 4 } 5 6 class FootballEquipmentFactory extends EquipmentFactory { 7 8 @Override 9 public Jersey createJersey() { 10 return new FootballJersey(); 11 } 12 13 @Override 14 public Shoe createShoe() { 15 return new FootballShoe(); 16 } 17 } 18 19 class BasketballEquipmentFactory extends EquipmentFactory { 20 21 @Override 22 public Jersey createJersey() { 23 return new BasketballJersey(); 24 } 25 26 @Override 27 public Shoe createShoe() { 28 return new BasketballShoe(); 29 } 30 31 }
某天你想要踢球了,客户端只须要依赖一个工厂,就能生产出一个产品族。
1 public static void main(String[] args) { 2 EquipmentFactory equipmentFactory = new FootballEquipmentFactory(); 3 Jersey jersey = equipmentFactory.createJersey(); 4 Shoe shoe = equipmentFactory.createShoe(); 5 jersey.putOn(); 6 shoe.putOn(); 7 }
输出:
在实际的项目中,抽象工厂用得最多的就是用来适应不一样的数据库类型。
因为类型不一样,得到的数据库链接,数据库用户等信息不一样,可构建一个产品族。
以上~请大神们鞭挞。