您的位置:首页 > 其它

《Head First 设计模式》之工厂方法模式

2014-07-15 22:38 218 查看
书上举的例子讲的是创建各个不同城市的PizzaStore的例子,感觉不是一两句话讲的清的,还是直接看模式的定义吧,然后对比实际的例子返回到定义和类图,这样应该会更有感觉。

工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类



下面的代码和书上的代码有出入,只是为了反映工厂方法的基本,没有书上的全,如果需要全部的代码,还是看书对应的源代码

1.Creator类,PizzaStore类是一个抽象类,其中的factoryMethod方法是createPizza方法

package factorymethod;

public abstract class PizzaStore {
public Pizza orderPizza(String type){
Pizza pizza;
pizza = createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
pizza.box();
return pizza;
}

abstract Pizza createPizza(String type);
}
2. NYPizzaStore是PizzaStore的具体实现类,仅实现了工厂方法createPizza

package factorymethod;

public class NYPizzaStore extends PizzaStore {

@Override
Pizza createPizza(String type) {
if(type.equals("cheese")){
return new NYStyleCheesePizza();
}
else return null;
}

}
3.Product类,这里是Pizza类

package factorymethod;

import java.util.ArrayList;

public abstract class Pizza {
String name;
String dough;
String sauce;
ArrayList toppings = new ArrayList();

void prepare(){
System.out.println("Preparing "+name);
for (int i = 0; i < toppings.size(); i++) {
System.out.println("    "+toppings.get(i));
}
}

void bake(){
System.out.println("Bake for 25 minutes at 350");
}

void cut(){
System.out.println("Cutting the pizza into diagonal slices");
}

void box(){
System.out.println("Place pizza in official PizzaStore box");
}

public String getName(){
return name;
}
}
4.具体产品类,这里是继承Pizza类

package factorymethod;

public class NYStyleCheesePizza extends Pizza {
public NYStyleCheesePizza(){
name = "NY Style Sauce and Cheese Pizza";
dough = "Thin Crust Dough";
sauce = "Marinara Sauce";

toppings.add("Grated Reggiano Cheese");
}
}
5.测试类
package factorymethod;

public class PizzaTestDrive {
public static void main(String[] args) {
PizzaStore nyStore = new NYPizzaStore();
Pizza pizza = nyStore.orderPizza("cheese");
System.out.println("Ethan ordered a"+pizza.getName()+"\n");
}
}


书上还用该模式引用了一个设计原则,依赖倒置原则:要依赖抽象,不要依赖具体类。书上说这个原则说明了:不能让高层组件依赖底层组件,而是不管高层组件和底层组件,“两者”都应该依赖与抽象。而所谓的“高层”组件,是由其他底层组件定义其行为的类。如本例中的PizzaStore是个高层组件,因为他的行为是由披萨定义的。这个依赖倒置我理解的还是不是很深,感觉可能是代码或者业务接触少了。

其中还有两个概念是依赖注入和控制反转,参考的文章http://openwares.net/java/dip_ioc_di.html

控制反转IoC(Inversion of Control)

通常情况下,class A依赖于class B,或者应用DIP之后依赖于Interface B,那么在运行时,我们必须自行主动的去实例化Interface B接口的实现类实例,然后将其引用传递给Class A,在传统的编程模型下,我们经常这样干。这样耦合度仍然很高,我们必须知道所依赖的实现类的一些细节。

而IoC则是将实例化被依赖模块的责任交出去,不再主动去做依赖装配工作,这样我们就可以彻底的只针对接口编程,而无需关心具体的实现。

IoC容器成为一个系统的对象容器和粘合剂,它负责创建对象的实例,并按照它们声明的依赖关系把它们粘合起来共同工作。通过配置文件或注解的方法,IoC容器会自动的满足模块之间的依赖关系,而无需我们再主动去处理依赖关系,只要被动接受就可以了。

这种依赖关系的满足由主动实现到被动接受的转变,就是所谓的控制反转了。其中依赖注入是实现控制反转的主要方式。

总的来讲,依赖倒置(DIP)是一种设计原则,控制反转(IoC)是一种处理对象间依赖关系的方式,与传统的主动方式正好相反,而依赖注入(DI)则是IoC容器实现控制反转的主要方式。

工厂方法模式的应用,在Spring中有一个FactoryBean,是Spring容器提供的一种可以扩展容器对象实例化逻辑的接口,FactoryBean只是一个Bean而已,主语是Bean,定语是Factory,不要和BeanFactory弄混淆,BeanFactory是一个生产Bean的工厂,主语是Factory,定语是Bean。当我们实现FactoryBean接口,实现它的Object
getObject()方法,该方法就会返回该FactoryBean“生产”的对象实例,然后就可以再xml文件中像其他bean一样定义了,其中调用getBean("beanId")方法直接会返回的“生产”的对象实例,如果在spring中需要获得该FactoryBean,则需要加上&,如getBean("&beanId")。

如果文章有什么错误或者有什么建议,欢迎提出,大家共同交流,一起进步

文章转载请注明出处,请尊重知识产权
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: