设计模式之工厂模式
当我们只用new去创建一个类时,我们就在针对这个具体类编程。如果能够不使用具体类,而是针对接口编程,将会对以后扩展有很大方便。 情景: 你是一个披萨店的老板,披萨有很多种类。 我们可能需要这么做 </span><span style="color: #0000ff;">if</span> (type == <span style="color: #800000;">A</span><span style="color: #000000;">) {
pizza </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> APizza();
} </span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (type == <span style="color: #800000;">B</span><span style="color: #000000;">) {
pizza </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> BPizza();
} </span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (type == <span style="color: #800000;">C</span><span style="color: #000000;">) {
pizza </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> CPizza();
}
... </span><span style="color: #008000;">//</span><span style="color: #008000;"> 制作披萨订单的其他操作</span>
} 但是以后我们可能会有D,E,F....之列的更多的披萨。我们必须重新修改这份代码。 根据“封装变化”的设计原则,我们需要把创建对象的部分封装起来。 =
</span><span style="color: #0000ff;">if</span> (type.equals("A"<span style="color: #000000;">)) {
pizza </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> APizza();
} </span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (type.equals("B"<span style="color: #000000;">)) {
pizza </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> BPizza();
} </span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (type.equals("C"<span style="color: #000000;">)) {
pizza </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> CPizza();
}
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> pizza;
}
} 这样在制作订单时只需在工厂取一个Pizza就可以了。 </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> PizzaStore(SimplePizzaFactory factory) {
</span><span style="color: #0000ff;">this</span>.factory =<span style="color: #000000;"> factory;
}
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> Pizza orderPizza(String type) {
Pizza pizza;
pizza </span>=<span style="color: #000000;"> factory.createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> pizza;
}
}
现在有很地区要建立披萨店的分店,你希望所有的店都有相同的流程,但是不同的地区会有不同的口味,比如有些地方只吃DEF口味的披萨,也就是说不同地区要有不同的工厂,没有方法把Pizza的制作活动全部局限于PizzaStore类呢? 方法是把createPizza放进PizzaStore类中,并设置成抽象方法,具体实现由每一个地区的子类完成。 </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> Pizza orderPizza(String type) {
Pizza pizza;
pizza </span>=<span style="color: #000000;"> createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> pizza;
}
</span><span style="color: #0000ff;">abstract</span><span style="color: #000000;"> Pizza createPizza(String type);
}
Product factoryMethod(String type)?
我们最一开始的代码,PizzaStore的实现是依赖于具体Pizza类的,使用工厂模式后,它已经不再依赖于具体的披萨类,也就是减少了对具体类的依赖。
?这个原则说明了,不要让高层组件依赖底层组件,而且,不管高层组件还是底层组件,两者都应该依赖抽象。 使用了工厂方法模式之后,PizzaStore类依赖Pizza这个接口,而具体的APizza,BPizza等具体披萨类也依赖于Pizza这个接口,这就是一种依赖倒置。 ……………… 现在又有一个新的问题 就是具体Pizza的制作。上面没有写具体披萨的制作过程,默认都是一样的。但是!不同地区用到原料也可能有不同,例如A地产辣椒和B地是不一样的,于是,我们还应该给Pizza写一个原料工厂~~~ 首先为工厂定义一个接口 为每一个地区创建一个原料工厂,比如纽约的原料工厂 NYPizzaIngredientFactory
@Override
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> Dough createDough() {
</span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">new</span><span style="color: #000000;"> ThinCrustDough();
}
@Override
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> Sauce createSauce() {
</span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">new</span><span style="color: #000000;"> MarinaraSauce();
}
@Override
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> Cheese createCheese() {
</span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">new</span><span style="color: #000000;"> ReggianoCheese();
}
@Override
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> Veggies[] createVeggies() {
Veggies[] veggies </span>= { <span style="color: #0000ff;">new</span> Garlic(),<span style="color: #0000ff;">new</span> Onion(),<span style="color: #0000ff;">new</span> Mushroom(),<span style="color: #0000ff;">new</span><span style="color: #000000;"> RedPepper() };
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> veggies;
}
@Override
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> Pepperoni createPepperoni() {
</span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">new</span><span style="color: #000000;"> SlicedPepperni();
}
@Override
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> Clams createClam() {
</span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">new</span><span style="color: #000000;"> FreshClams();
}
} 抽象的Pizza类 String name;
Dough dough;
Sauce sauce;
Veggies veggies[];
Cheese cheese;
Pepperoni pepperoni;
Clams clams;
</span><span style="color: #0000ff;">abstract</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> prepare();
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> bake() {
System.out.println(</span>"Bake for 25 minutes at 350."<span style="color: #000000;">);
}
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> cut() {
System.out.println(</span>"Cutting the pizza into diagonal slices."<span style="color: #000000;">);
}
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> box() {
System.out.println(</span>"Place pizza in official PizzaStore box."<span style="color: #000000;">);
}
</span><span style="color: #0000ff;">void</span><span style="color: #000000;"> setName(String name) {
</span><span style="color: #0000ff;">this</span>.name =<span style="color: #000000;"> name;
}
String getName() {
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> name;
}
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> String toString() {
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> name;
}
} 具体的Pizza类。每个Pizza的制作流程其实是一样的。只有原料不同,同时原料会和地点有关。为具体的类添加一个原料工厂。 CheesePizza
PizzaIngredientFactory ingredientFactory;
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> CheesePizza(PizzaIngredientFactory ingredientFactory) {
</span><span style="color: #0000ff;">this</span>.ingredientFactory =<span style="color: #000000;"> ingredientFactory;
}
@Override
</span><span style="color: #0000ff;">void</span><span style="color: #000000;"> prepare() {
System.out.println(</span>"Preparing " +<span style="color: #000000;"> name);
dough </span>=<span style="color: #000000;"> ingredientFactory.createDough();
sauce </span>=<span style="color: #000000;"> ingredientFactory.createSauce();
cheese </span>=<span style="color: #000000;"> ingredientFactory.createCheese();
}
} 纽约的PizzaStore类 NYPizzaStore
@Override
Pizza createPizza(String item) {
Pizza pizza </span>= <span style="color: #0000ff;">null</span><span style="color: #000000;">;
PizzaIngredientFactory ingredientFactory </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> NYPizzaIngredientFactory();
</span><span style="color: #0000ff;">if</span> (item.equals("cheess"<span style="color: #000000;">)) {
pizza </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> ChessPizza(ingredientFactory);
} </span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (item.equals("veggie"<span style="color: #000000;">)) {
pizza </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> VeggiePizza();
pizza.setName(</span>"New York Style Veggie Pizza."<span style="color: #000000;">);
}
</span><span style="color: #008000;">//</span><span style="color: #008000;"> else if .... 还有其他种类的Pizza </span>
<span style="color: #0000ff;">return</span><span style="color: #000000;"> pizza;
}
} 完成~~ 我们引入了新类型的工厂,也就是所谓的抽象工厂,来创建披萨家族。 抽象工程模式:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。 抽象工厂允许客户使用抽象类的接口来创建一组相关的产品,而不需要知道(或关心)实际产出的具体产品是什么。这样一来,客户就从具体产品中被解耦。 类图 工厂方法模式通过继承,而抽象工厂模式是通过组合实现。 抽象工厂是用来创建一个产品家族的抽象类型,可以把一群相关产品集合起来。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |