工厂方法模式
更新日期:
工厂模式
——实例化可能不公开。
——识别变化的部分,封装变化的部分,封装创建对象的代码。
简单工厂编程习惯:1
public class SimplePizzaFactory
{
public Pizza createPizza(String type)
{
Pizza pizza = null;
...
}
public class PizzaStore
{
SimplePizzaFactory factory;
public PizzaStore(SimplePizzaFactory factory)
{
this.factory = factory;
}
public Pizza orderPizza(String type)
{
Pizza pizza;
pizza = factory.createPizza(type);
//此处不用new创建对象
}
}
}
——abstract Produce factoryMethod (String type)
工厂方法:将客户点披萨orderPizza()和实际创建具体产品的代码分隔开。
——调用使用:1
PizzaStore nyPizzaStore = new NYPizzaStore();//建立实例
nyPizzaStore.orderPizza("cheese");
//相当于隐含调用 Pizza pizza = createPizza("cheese");
——工厂模式:用来封装对象的创建。【封装改变】让子类决定创建什么对象。
工厂方法模式:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
——依赖倒置原则:
要依赖抽象,不要依赖具体类。
不能让高层组件依赖底层组件。而且不管高层或底层组件,都应该依赖于抽象。
依赖抽象层,而不依赖具体类。
1.变量不持有具体类的引用,避开new。
2.不让类派生自具体类,请派生自一个抽象(接口或抽象类)
3.不覆盖基类中已实现的方法。
抽象工厂模式:
提供一个接口,用于创建相关或依赖对象的家族。而不许奥明确指定具体类。
(通过对象的组合)
1 | public interface PizzaIngredientFactory { public Dough createDough(); public Sauce createSauce(); ... } public class NYPizzaIngredientFactory implements PizzaIngredientFactory { public Dough createDough(){ return new ThinCrustDough(); } public Sauce createSauce(){ return new MarinareSource(); } } public abstract class Pizza{ String name; Dough dough; Sauce sauce; abstract void prepare(); void cut(){...} } public class CheesePizza extends Pizza{ PizzaIngredientFactory ingredientFactory;//对象组合 public CheesePizza(PizzaIngredientFactory ing){ this.ingredientFactory = ing; } void prepare(){ //工厂创建对象 dough = ingredientFactory.createDough(); } } public class NYPizzaStore extends PizzaStore{ protected Pizza createPizza(String item){ Pizza pizza = null; PizzaIngredientFactory ing = new NYPizzaIngredientFactory(); if(item.equals("cheese")){ //把工厂对象作为参数传入构造函数 pizza = new CheesePizza(ing); 【比如也可以传new CheesePizza(new GuangZhouPizzaIngredientFactory())】 pizza.setName("NY Cheese"); } return pizza; } } |
《Java工厂模式》
http://blog.csdn.net/zxl0016/article/details/7922384
有一个户,他家有三辆汽车——Benz奔驰、Bmw宝马、Audi奥迪,还雇了司机为他开车。不过,户坐车时总是怪怪的:上Benz车后跟司机说“开奔驰车!”,坐上Bmw后他说“开宝马车!”,坐上Audi说“开奥迪车!”。你一定说:这人有病!直接说开车不就行了?!
工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。
工厂模式在《Java与模式》中分为三类:
1)简单工厂模式(Simple Factory)
2)工厂方法模式(Factory Method)
3)抽象工厂模式(Abstract Factory)
这三种模式从上到下逐步抽象,并且更具一般性。
GOF在《设计模式》一书中将工厂模式分为两类:工厂方法模式(FactoryMethod)与抽象工厂模式(Abstract Factory)。将简单工厂模式(SimpleFactory)看为工厂方法模式的一种特例,两者归为一类。
两者皆可,在本文使用《Java与模式》的分类方法。下面来看看这些工厂模式是怎么来“治病”的。
简单工厂模式
又称静态工厂方法模式。
目的:定义一个用于创建对象的接口。
//抽象产品角色1
public interface Car{
public void drive();
}
//具体产品角色1
public class Benz implements Car{
public void drive() {
System.out.println("Driving Benz ");
}
}
public class Bmw implements Car{
public void drive() {
System.out.println("Driving Bmw ");
}
}
//工厂类角色1
public class Driver{
//工厂方法.注意 【返回类型为抽象产品角色】
public static Car driverCar(String s)throws Exception{
//判断逻辑,返回具体的产品角色给Client
if(s.equalsIgnoreCase("Benz"))
return new Benz();
else if(s.equalsIgnoreCase("Bmw"))
return new Bmw();
......
else throw new Exception();
。。。
1 | //欢迎****户出场...... public class Magnate{ public static void main(String[] args){ try{ //告诉司机我今天坐奔驰 Car car = Driver.driverCar("benz"); //下命令:开车 car.drive(); 。。。 |
客户端免除了直接创建产品对象的责任,而仅仅负责“消费”产品。
工厂方法模式
工厂方法模式去掉了简单工厂模式中工厂方法的静态属性,使得它可以被子类继承。这样在简单工厂模式里集中在工厂方法上的压力可以由工厂方法模式里不同的工厂子类来分担。
你应该大致猜出了工厂方法模式的结构,来看下它的组成:
1)抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。
2)具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。
3)抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。
4)具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。
工厂方法模式使用继承自抽象工厂角色的多个子类来代替简单工厂模式中的“上帝类”。正如上面所说,这样便分担了对象承受的压力;而且这样使得结构变得灵活起来——当有新的产品(即****户的汽车)产生时,只要按照抽象产品角色、抽象工厂角色提供的合同来生成,那么就可以被客户使用,而不必去修改任何已有的代码。可以看出工厂角色的结构也是符合开闭原则的!
我们还是老规矩,使用一个完整的例子来看看工厂模式各个角色之间是如何来协调的。话说****户生意越做越大,自己的爱车也越来越多。这可苦了那位司机师傅了,什么车它都要记得,维护,都要经过他来使用!于是****户同情他说:看你跟我这么多年的份上,以后你不用这么辛苦了,我给你分配几个人手,你只管管好他们就行了!于是,工厂方法模式的管理出现了。代码如下:
代码:
//抽象产品角色,具体产品角色与简单工厂模式类似,只是变得复杂了些,这里略。
//抽象工厂角色1
public interface Driver{
public Car driverCar();
}
public class BenzDriver implements Driver{
public Car driverCar(){
return new Benz();
}
}
public class BmwDriver implements Driver{
public Car driverCar(){
return new Bmw();
}
}
//应该和具体产品形成对应关系…
//有请**户先生1
public class Magnate{
public static void main(String[] args){
try{
Driver driver = new BenzDriver();
Car car = driver.driverCar();
【工厂方法】
car.drive();
}
……
}
可以看出工厂方法的加入,使得对象的数量成倍增长。当产品种类非常多时,会出现大量的与之对应的工厂对象,这不是我们所希望的。因为如果不能避免这种情况,可以考虑使用简单工厂模式与工厂方法模式相结合的方式来减少工厂类:即对于产品树上类似的种类(一般是树的叶子中互为兄弟的)使用简单工厂模式来实现。
五、小结
工厂方法模式仿佛已经很完美的对对象的创建进行了包装,使得客户程序中仅仅处理抽象产品角色提供的接口。那我们是否一定要在代码中遍布工厂呢?大可不必。也许在下面情况下你可以考虑使用工厂方法模式:
1)当客户程序不需要知道要使用对象的创建过程。
2)客户程序使用的对象存在变动的可能,或者根本就不知道使用哪一个具体的对象。
简单工厂模式与工厂方法模式真正的避免了代码的改动了?没有。在简单工厂模式中,新产品的加入要修改工厂角色中的判断语句;而在工厂方法模式中,要么将判断逻辑留在抽象工厂角色中,要么在客户程序中将具体工厂角色写死(就象上面的例子一样)。而且产品对象创建条件的改变必然会引起工厂角色的修改。
面对这种情况,Java的反射机制与配置文件的巧妙结合突破了限制——这在Spring中完美的体现了出来。
抽象工厂模式
先来认识下什么是产品族: 位于不同产品等级结构中,功能相关联的产品组成的家族。还是让我们用一个例子来形象地说明一下吧。
回到抽象工厂模式的话题上。
可以说,抽象工厂模式和工厂方法模式的区别就在于需要创建对象的复杂程度上。而且抽象工厂模式是三个里面最为抽象、最具一般性的。
抽象工厂模式的用意为:给客户端提供一个接口,可以创建多个产品族中的产品对象
而且使用抽象工厂模式还要满足一下条件:
1)系统中有多个产品族,而系统一次只可能消费其中一族产品。
2)同属于同一个产品族的产品以其使用。
来看看抽象工厂模式的各个角色(和工厂方法的如出一辙):
1)抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。
2)具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。在java中它由具体的类来实现。
3)抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。
4)具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。
看过了前两个模式,对这个模式各个角色之间的协调情况应该心里有个数了,我就不举具体的例子了。只是一定要注意满足使用抽象工厂模式的条件哦。