以去餐厅吃饭为例。理解一下简单工厂-工厂方法-抽象工厂的区别于关联。
1. 简单工厂
由一个工厂对象决定创建出哪一种产品类的实例。
- 一个具体工厂通过条件语句创建多个产品,产品的创建逻辑集中与一个工厂类。
- 客户端通过传不同的参数给工厂,实现创建不同产品的目的
- 增加新产品时,需要修改工厂类、增加产品类,不符合OCP原则
人去吃食物(酒,肉),店只有一家,需要指定要什么。好比餐厅就一个厨房,同时提供酒和肉。
由Factory根据出入的参数直接创建出ConcreteFood。
abstract class Food{
public abstract String getEatable();
}
class Alcohol extends Food{
public String getEatable(){
return"alcohol";
}
}
class Meat extends Food{
public String getEatable(){
return"meat";
}
}
class Factory{
public Food getFood(String food)throws Exception{
if(food.equals("alcohol")){
return new Alcohol();
}else if(food.equals("meat")){
return new Meat();
}
throw new Exception("No "+food);
}
}
public class Man{
public void eat(){
Factory factory=new Factory();
Food food=null;
//eat alcohol
try {
food=factory.getFood("alcohol");
} catch (Exception e) {
e.printStackTrace();
}
print(food.getEatable());
//eat meat
try {
food=factory.getFood("meat");
} catch (Exception e) {
e.printStackTrace();
}
print(food.getEatable());
}
public void print(String str){
System.out.println("I eat "+str+" .");
}
public static void main(String[] args){
Man man=new Man();
man.eat();
}
}
输出:
I eat alcohol .
I eat meat .
2. 工厂方法:
- 一个工厂创建一个产品,所有的具体工厂继承自一个抽象工厂。
- 客户端先创建不同产品的工厂,再由工厂创建具体产品,产品的创建逻辑分散在每个具体工厂类中。
- 客户端只依赖于抽象工厂与抽象产品,不依赖任何具体的工厂与具体产品
- 增加新产品时,需要增加工厂类和产品类,符合OCP原则
人去吃食物(酒,肉),店只有两家,一家只卖酒,一家只卖肉,不需要指定要什么,只要走到需要买食物的那家就行了。好比餐厅有多个厨房,每个厨房有分工,只提供一种食物,而不需要在一个厨房里面拥挤地摆放多种食物。
工厂方法在简单工厂之上,工厂方法将产品的具体创建给子类完成,这样在需要增加食物种类时,不用修改Factory,只需要添加相应的ConcreteFactory和ConcreteFood.
abstract class Food{
public abstract String getEatable();
}
class Alcohol extends Food{
public String getEatable(){
return"alcohol";
}
}
class Meat extends Food{
public String getEatable(){
return"meat";
}
}
abstract class Factory{
public abstract Food getFood();
}
class AlcoholFactory extends Factory{
public Food getFood(){
return new Alcohol();
}
}
class MeatFactory extends Factory{
public Food getFood(){
return new Meat();
}
}
public class Man{
public void eat(){
Factory factory=null;
Food food=null;
//eat alcohol
factory=new AlcoholFactory();
food=factory.getFood();
print(food.getEatable());
//eat meat
factory=new MeatFactory();
food=factory.getFood();
print(food.getEatable());
}
public void print(String str){
System.out.println("I eat "+str+" .");
}
public static void main(String[] args){
Man man=new Man();
man.eat();
}
}
输出:
I eat alcohol .
I eat meat .
3. 抽象工厂
- 一个具体工厂创建一个产品族,一个产品族是不同系列产品的组合,产品的创建的逻辑分在在每个具体工厂类中。所有的具体工厂继承自同一个抽象工厂。
- 客户端创建不同产品族的工厂,产品族的工厂创建具体的产品对客户端是不可见的。
- 增加新的产品族时,需要增加具体工厂类,符合OCP原则。
- 增加新产品时,需要修改具体工厂类和增加产品类,不符合OCP原则
- 如果没有应对“多系列对象创建”的需求变化,则没有必要使用抽象工厂模式,这时候使用简单的静态工厂完全可以。
人去吃食物(酒,肉),店只有两家,一家只卖酒,一家只卖肉,不需要指定要什么,只要走到需要买食物的那家就行了。但是不能用手拿着吃吧,在买酒的时候,同时买个杯子;在买肉的时候,同时买个小刀。好比是每个厨房除了提供对应食物,还提供与该食物匹配的其他服务,比方说餐具,即把高内聚封装。
抽象工厂在工厂方法之上,主要针对于创建多个不同的产品族,而不是只有Food,还有TableWare。我理解的抽象工厂创建的是一整个体系,而不是单一的功能,就像是饭店,提供给你整个餐饮服务,有食物,餐具,包厢,工厂方法就像是餐厅里面的厨房,只提供食物。
abstract class Food{
public abstract String getEatable();
}
class Alcohol extends Food{
public String getEatable(){
return"alcohol";
}
}
class Meat extends Food{
public String getEatable(){
return"meat";
}
}
abstract class TableWare{
public abstract String getTool();
}
class Cup extends TableWare{
public String getTool(){
return"cup";
}
}
class Knife extends TableWare{
public String getTool(){
return"knife";
}
}
abstract class Factory{
public abstract Food getFood();
public abstract TableWare getTableWare();
}
class AlcoholFactory extends Factory{
public Food getFood(){
return new Alcohol();
}
public TableWare getTableWare(){
return new Cup();
}
}
class MeatFactory extends Factory{
public Food getFood(){
return new Meat();
}
public TableWare getTableWare(){
return new Knife();
}
}
public class Man{
public void eat(){
Factory factory=null;
Food food=null;
TableWare tableWare=null;
//eat alcohol
factory=new AlcoholFactory();
food=factory.getFood();
tableWare=factory.getTableWare();
print(food.getEatable(),tableWare.getTool());
//eat meat
factory=new MeatFactory();
food=factory.getFood();
tableWare=factory.getTableWare();
print(food.getEatable(),tableWare.getTool());
}
public void print(String food,String tableWare){
System.out.println("I eat "+food+" by "+tableWare+" .");
}
public static void main(String[] args){
Man man=new Man();
man.eat();
}
}
输出:
I eat alcohol by cup .
I eat meat by knife .
参考:
http://blog.youkuaiyun.com/dylan_ren/article/details/1680430
http://tech.ddvip.com/2012-10/1350629930183788_2.html