从设计模式的类型上来说,简单工厂模式是属于创建型模式,又叫做静态工厂方法(StaticFactory Method)模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。
其包括三个角色:
其UML图如下所示:
看一下写的小例子:假如一家航空公司需要购买飞机:
先定义飞机接口:
public interface IPlane { void name(); }
波音:
public class Boeing777 implements IPlane{ private String name = "Boeing777"; @Override public void name() { // TODO Auto-generated method stub System.out.println("My name is:" + name); } }
public class Boeing737 implements IPlane { private String name = "Boeing737"; @Override public void name() { // TODO Auto-generated method stub System.out.println("My name is :" + name); } }
Create:
public class PlaneFactory { public static IPlant getPlane(String name) throws Exception { if (name.equalsIgnoreCase("boeing777")){ return new Boeing777(); } else if (name.equalsIgnoreCase("boeing737")){ return new Boeing737(); }else { throw new Exception("The type $type don't exists" ); } } }
public class PlaneTest { /** * @param args * @throws Exception */ public static void main(String[] args) throws Exception { // TODO Auto-generated method stub //获取波音飞机 IPlane boeing777 = PlaneFactory.getPlane("boeing777"); //获得名字 boeing777.name(); //获取空客飞机 IPlane boeing737= PlaneFactory.getPlane("airbus"); //获得名字 boeing737.name(); } }
My name is:Boeing777
My name is :Boeing737
优点:
工厂类是整个模式的关键.包含了必要的逻辑判断,根据外界给定的信息,决定究竟应该创建哪个具体类的对象.通过使用工厂类,外界可以从直接创建具体产品对象的尴尬局面摆脱出来,仅仅需要负责“消费”对象就可以了。而不必管这些对象究竟如何创建及如何组织的.明确了各自的职责和权利,有利于整个 软件体系结构 的优化。 缺点: 由于工厂类集中了所有实例的创建逻辑,违反了 高内聚 责任分配原则,将全部创建逻辑集中到了一个工厂类中;它所能创建的类只能是事先考虑到的,如果需要添加新的类,则就需要改变工厂类了。 当系统中的具体产品类不断增多时候,可能会出现要求工厂类根据不同条件创建不同实例的需求.这种对条件的判断和对具体产品类型的判断交错在一起,很难避免模块功能的蔓延,对系统的维护和扩展非常不利; 这些缺点在 工厂方法模式 中得到了一定的克服。 使用场景 工厂类负责创建的对象比较少; 客户只知道传入工厂类的参数,对于如何创建对象(逻辑)不关心;由于简单工厂很容易违反高内聚责任分配原则,因此一般只在很简单的情况下应用。
说明:以上文字概念部分,均来自百度百科。自己没有那么好的归纳能力。
5月23号修改工厂模式代码,把工厂类修改成抽象类:
public abstract class PlaneFactory { public void letPlaneFly(String name){ IPlane iPlane = getPlane(name); iPlane.fly(); } abstract IPlane getPlane(String name) ; }
具体工厂类,有boeing工厂和airbus工厂。
public class AirbusFactory extends PlaneFactory { @Override IPlane getPlane(String name) { // TODO Auto-generated method stub if (name.equalsIgnoreCase("airbus320")){ return new Airbus320(); } else if (name.equalsIgnoreCase("airbus380")){ return new Airbus380(); }else { return null; } } }
public class BoeingPlaneFactory extends PlaneFactory{ @Override IPlane getPlane(String name) { // TODO Auto-generated method stub if (name.equalsIgnoreCase("boeing777")){ return new Boeing777(); } else if (name.equalsIgnoreCase("boeing737")){ return new Boeing737(); }else { return null; } } }
public abstract class IPlane { abstract void name(); public void fly() { name(); System.out.println("i fly in the sky"); } }
public class Boeing777 extends IPlane { @Override public void name() { // TODO Auto-generated method stub System.out.println("i am boeing 777"); } }
public class Boeing737 extends IPlane { @Override public void name() { // TODO Auto-generated method stub System.out.println("i am boeing 737"); } }
public class Airbus320 extends IPlane { @Override public void name() { // TODO Auto-generated method stub System.out.println("i am airbus320"); } }
public class Airbus380 extends IPlane { @Override public void name() { // TODO Auto-generated method stub System.out.println("i am Airbus380"); } }
public static void main(String[] args) throws Exception { PlaneFactory airBus = new AirbusFactory(); //看空客飞机飞 airBus.letPlaneFly("airbus320"); airBus.letPlaneFly("airbus380"); PlaneFactory boeing = new BoeingPlaneFactory(); boeing.letPlaneFly("boeing777"); boeing.letPlaneFly("boeing737"); }
i am airbus320
i fly in the sky
i am Airbus380
i fly in the sky
i am boeing 777
i fly in the sky
i am boeing 737
i fly in the sky
当我们发现,我们不仅需要民航飞机,我们还需要战斗机,该如何办呢?大家都知道,波音不仅生产民用飞机,还有著名的B-52,而空客也有它的军用运输机A400M。
我们生产飞机时,就需要两个接口了,军用飞机一个接口,民用飞机一个接口。看下图:
军用飞机是一个产品等级,民用飞机又是一个产品等级,而波音和空客生产两个不同的产品族。
先看看民用飞机接口:
public interface ICivilaircraft { String getName(); //运输旅客 void passengers(); }
public class Boeing777 implements ICivilaircraft{ private String name ="Boeing 777"; private String personNumber ="350"; @Override public String getName() { return name; // TODO Auto-generated method stub } @Override public void passengers() { // TODO Auto-generated method stub System.out.println(getName()+"can passengers "+personNumber+" person"); } }
public class Airbus340 implements ICivilaircraft{ private String name ="Airbus340"; private String personNumber ="380"; @Override public String getName() { return name; // TODO Auto-generated method stub } @Override public void passengers() { // TODO Auto-generated method stub System.out.println(getName()+"can passengers "+personNumber+" person"); } }
军用飞机接口:
public interface IWarplane { String getName(); //运输武器 void Transportarms(); }
public class A400M implements IWarplane { private String name ="A400M"; private String armweight="30吨"; @Override public String getName() { // TODO Auto-generated method stub return name; } @Override public void Transportarms() { // TODO Auto-generated method stub System.out.println(getName()+"can transport "+ armweight+" arms"); } }
public class B52 implements IWarplane { private String name ="B52"; private String armweight="27吨"; @Override public String getName() { // TODO Auto-generated method stub return name; } @Override public void Transportarms() { // TODO Auto-generated method stub System.out.println(getName()+"can transport "+ armweight+" arms"); } }
public abstract class AbstractFactory { abstract ICivilaircraft getCivilair(); abstract IWarplane getWarplane(); }
public class BoeingFactory extends AbstractFactory{ @Override ICivilaircraft getCivilair() { // TODO Auto-generated method stub return new Boeing777(); } @Override IWarplane getWarplane() { // TODO Auto-generated method stub return new B52(); } }
public class AirBus extends AbstractFactory { @Override ICivilaircraft getCivilair() { // TODO Auto-generated method stub return new Airbus340(); } @Override IWarplane getWarplane() { // TODO Auto-generated method stub return new A400M(); } }
public static void main(String[] args) { // TODO Auto-generated method stub AbstractFactory boeing = new BoeingFactory(); AbstractFactory airbus = new AirBus(); //查看波音的民用飞机 boeing.getCivilair().passengers(); //查看波音的军用飞机 boeing.getWarplane().Transportarms(); //查看空客的民用飞机 airbus.getCivilair().passengers(); //查看空客的军用飞机 airbus.getWarplane().Transportarms(); }
测试结果:
Boeing 777 can passengers 350 person
B52 can transport 27吨 arms
Airbus340 can passengers 380 person
A400M can transport 30吨 arms
区别和联系:
抽象工厂和工厂模式有什么区别呢?他们俩又在具体什么情况下使用呢?请看下面从网上找到的不错的回答:
其实这两者的区别,GOF的书上说得很清楚。工厂方法采用的是类继承机制(生成一个子类,重写该工厂方法,在该方法中生产一个对象)。而抽象工厂采用的是对象组合机制,专门定义“工厂”对象来负责对象的创建。对象组合的方式就是把“工厂”对象作为参数传递。
工厂方法模式: 一个抽象产品类,可以派生出多个具体产品类。 一个抽象工厂类,可以派生出多个具体工厂类。 每个具体工厂类只能创建一个具体产品类的实例。 抽象工厂模式: 多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。 一个抽象工厂类,可以派生出多个具体工厂类。 每个具体工厂类可以创建多个具体产品类的实例。 区别: 工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。 工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。
工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。工厂方法:说白了就是一个方法,这个方法是创建具体的产品的,它要求所有的工厂都具有同一个签名的方法,必要时重写该方法;抽象工厂:不能直接创建产品,只能创建工厂,即抽象工厂创建的产品是工厂。虽然它也定义了创建产品的方法,但需要创建出来的具体的工厂实现,即:抽象工厂创建出的工厂创建产品。工厂方法采用的是类继承机制(生成一个子类,重写该工厂方法,在该方法中生产一个对象);而抽象工厂采用的是对象组合机制,专门定义“工厂”对象来负责对象的创建。对象组合的方式就是把“工厂”对象作为参数传递。
可以这么去理解,“抽象工厂模式”这个称呼中的“抽象”是一个动词,即对工厂方法模式进行了抽象,就变成了抽象工厂模式,这么理解后,就不难看出它们的区别: 工厂方法模式:每个抽象产品派生多个具体产品类,每个抽象工厂类派生多个具体工厂类,每个具体工厂类负责一个具体产品的实例创建; 抽象工厂模式:每个抽象产品派生多个具体产品类,每个抽象工厂派生多个具体工厂类,每个具体工厂负责多个(一系列)具体产品的实例创建。