浏览 936 次
|
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
|---|---|
| 作者 | 正文 |
|
最后更新时间:2008-02-02 关键字: 设计模式
当你直接实例化一个对象时,就是在依赖它的具体类.很清楚地,代码里减少对于具体类的依赖是件"好事". //我们建造一个工厂来生产原料,开始为工厂定义一个接口,这个接口负责创建所有的原料:
public interface PizzaIngredientFactory {
//在接口中,每个原料都有一个对应的方法创建该原料
public Dough createDough();
public Sauce createSauce();
public Cheese createCheese();
public Veggies[] createVeggies();
public Pepperoni createPepperoni();
public Clams createClam();
//这里有许多新类,每个原料都是一个类,这里我就不写出来了
}
//再来创建纽约原料工厂,必须实现此接口,芝加哥原料工厂差不多
public class NYPizzaIngredientFactory implements PizzaIngredientFactory {
//对于原料家族内的每一种原料,我们都提供了纽约版本
public Dough createDough() {
return new ThinCrustDough();
}
public Sauce createSauce() {
return new MarinaraSauce();
}
public Cheese createCheese() {
return new ReggianoCheese();
}
//这里我们可以写的更好点,先用这个简单做法好了
public Veggies[] createVeggies() {
Veggies veggies[] = { new Garlic(), new Onion(), new Mushroom(), new RedPepper() };
return veggies;
}
public Pepperoni createPepperoni() {
return new SlicedPepperoni();//这是切片的意式腊肠
}
public Clams createClam() {
return new FreshClams();//新鲜的蛤俐
}
}
//工厂已经就绪,我们来重做披萨
public abstract class Pizza {
//每个披萨都持有一组在准备时会用到的原料
String name;
Dough dough;
Sauce sauce;
Veggies veggies[];
Cheese cheese;
Pepperoni pepperoni;
Clams clam;
//现在把prepare声明成抽象,在这个方法中我们需要收集披萨所需的原料,而这些原料当然来自原料工厂了
abstract void prepare();
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");
}
void setName(String name) {
this.name = name;
}
String getName() {
return name;
}
public String toString() {}
}
//现在已经有了一个抽象披萨,可以开始创建纽约和芝加哥风味的披萨了,从今以后,加盟店必须直接从工厂取得原料,下面是CheesePizza:
public class CheesePizza extends Pizza {
PizzaIngredientFactory ingredientFactory;
//要制作披萨,需要工厂提供原料,所以每个披萨类都需要从构造器参数中得到一个工厂,并把这个工厂存放在一个实例变量中
public CheesePizza(PizzaIngredientFactory ingredientFactory) {
this.ingredientFactory = ingredientFactory;
}
//神奇的事情发生在这里,每当需要原料时,就跟工厂要
void prepare() {
System.out.println("Preparing " + name);
dough = ingredientFactory.createDough();
sauce = ingredientFactory.createSauce();
cheese = ingredientFactory.createCheese();
}
}
//再来看看蛤俐披萨
public class ClamPizza extends Pizza {
PizzaIngredientFactory ingredientFactory;
//原料工厂
public ClamPizza(PizzaIngredientFactory ingredientFactory) {
this.ingredientFactory = ingredientFactory;
}
//要做出蛤俐披萨,prepare方法就必须从本地工厂取得正确的原料
void prepare() {
System.out.println("Preparing " + name);
dough = ingredientFactory.createDough();
sauce = ingredientFactory.createSauce();
cheese = ingredientFactory.createCheese();
clam = ingredientFactory.createClam();
}
}
//我们快完工了,再到加盟店短暂巡视一下,确认他们使用了正确的披萨,也需要让他们能和本地的原料工厂搭上线
public class NYPizzaStore extends PizzaStore {
protected Pizza createPizza(String item) {
Pizza pizza = null;
//纽约店由纽约披萨原料工厂负责生产所有纽约风味披萨所需的原料
PizzaIngredientFactory ingredientFactory =
new NYPizzaIngredientFactory();
//对于每一种披萨,我们实例化一个新的披萨,并传进该种披萨所需的工厂
if (item.equals("cheese")) {
//把工厂传递给每个披萨,以便披萨能从工厂中取得原料
pizza = new CheesePizza(ingredientFactory);
pizza.setName("New York Style Cheese Pizza");
} else if (item.equals("veggie")) {
pizza = new VeggiePizza(ingredientFactory);
pizza.setName("New York Style Veggie Pizza");
} else if (item.equals("clam")) {
pizza = new ClamPizza(ingredientFactory);
pizza.setName("New York Style Clam Pizza");
} else if (item.equals("pepperoni")) {
pizza = new PepperoniPizza(ingredientFactory);
pizza.setName("New York Style Pepperoni Pizza");
}
return pizza;
}
}一连串的代码改变,我们到底做了什么?我们引入了新的抽象工厂来创建原料家族.通过抽象工厂提供的接口书写代码,我们的代码将从实际工厂解耦,以便在不同上下文中实现各式各样的工厂,制作出各种不同的产品. 我们又在设计模式家族中新增了抽象工厂模式.抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类. 工厂方法和抽象工厂有什么区别呢? 声明:JavaEye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
|
|
| 返回顶楼 | |
|
最后更新时间:2008-03-08
呵呵,我这几天也在看HEAD FIRST的DESIGN PATTERN这本书。浅显易懂,生动有趣,可读性很强:)
不过在介绍SINGLETON模式的时候,这本书里漏了一个技术问题:书中在介绍多线程环境下的高性能(减少线程同步的开销)SINGLETON的时候,使用了double-checked locking。 事实上,对于java而言这是不合适的,好像是因为java的内存模型支持无序写造成的吧。 |
|
| 返回顶楼 | |



