一.前言
1.准备好开始烘烤某些松耦合的OO设计。
2.制造对象的方法除了new,还有很多其他的方法;
3.初始化使用new经常会带来一些耦合的问题,工厂模式可以解决这个问题;
那么“new”有什么不对劲呢?
其实,new没有问题,有问题的是“改变”。则可以用设计原则“找出会变化的部分,把他们从不变的部分分离出来”。
(即:将实例化具体类的方法抽离,或者封装起来,使他们不会干扰其他部分。)
4.重要原则--“针对接口编程”。
5.所有工厂模式都是用来封装对象的创建。
二.披萨店实例--简单工厂
1.pizza店有许多pizza类型,每种pizza从order开始的流程都要经过准备prepare、烘烤bake、切片cut和装箱box,所以通常对于OO设计者们,初步可以考虑到这样的设计:
public class MainTest {
public static void main(String[] args) {
IPizza pizza = orderPizza(null);
if(pizza != null){
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}
}
private static IPizza orderPizza(String type){
if(type == null){
System.out.println("What kind of pizza do you want?");
return null;
}
IPizza pizza = null;
if(type.equals("cheese")){
pizza = new PizzaCheese();
}else if(type.equals("fruit")){
pizza = new PizzaFruit();
}else if(type.equals("banana")){
pizza = new PizzaBanana();
}
return pizza;
}
}
public interface IPizza {
/**准备*/
public void prepare();
/**烘烤*/
public void bake();
/**切片*/
public void cut();
/**装盒*/
public void box();
}
public class PizzaCheese implements IPizza{
public void prepare() {
System.out.println("PizzaCheese prepare");
}
public void bake() {
System.out.println("PizzaCheese bake");
}
public void cut() {
System.out.println("PizzaCheese cut");
}
public void box() {
System.out.println("PizzaCheese box");
}
}
2.上述中存在一个问题:增加新类型pizza或去除一种卖的不好的pizza,上述创建pizza对象的部分就要一改再改,这里就是变化的部分,我们要做的,就是分离变化的部分----该使用封装了。
封装创建对象的代码。
(1)将创建对象的代码移到另一个对象中,这个对象的专职就是创建pizza对象;
(2)称这个专职对象为“工厂”SimplePizzaFactory;
(3)此时,orderPizza()就不再需要知道什么类型的pizza,只管得到一个pizza。
//测试类
public class MainTest {
public static void main(String[] args) {
//利用工厂创建pizza
IPizza pizza = new PizzaShop().orderPizza("banana");
if(pizza != null){
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}
}
}
//客户预订披萨
class PizzaShop{
public IPizza orderPizza(String type){
//利用工厂创建pizza
IPizza pizza = SimplePizzaFactory.createPizza(type);
return pizza;
}
}
public class SimplePizzaFactory {
/**
* 把原来的创建代码直接移动过来
* @param type
* @return
*/
public static IPizza createPizza(String type){
if(type == null){
System.out.println("What kind of pizza do you want?");
return null;
}
IPizza pizza = null;
if(type.equals("cheese")){
pizza = new PizzaCheese();
}else if(type.equals("fruit")){
pizza = new PizzaFruit();
}else if(type.equals("banana")){
pizza = new PizzaBanana();
}
return pizza;
}
}
其他部分不变,此后:
当有很多很多“客户”时,他们都利用该“工厂”创建指定类型的pizza,如果pizza本身种类等发生任何改变,每个“客户”都不用修改代码,只需“工 厂”修改即可。
3.以上就是“简单工厂”:
简单工厂其实并不是一个设计模式,而是一种编程习惯;
简单工厂常用为static,但有时也有缺点,不能利用继承待改变创建方法的行为。
三.披萨店实例--工厂方法
1.现有不同区域的披萨店想要做不同口味的披萨。就不能用简单工厂了。可以考虑将创建对象的功能移到pizzashop的一个抽象方法中,由pizzashop的子类做决定创建具体的对象。
public abstract class PizzaShop {
// final的修饰不是必要的,不过这样可以防止子类覆盖
public final IPizza orderPizza(String type){
// createPizza()移回PizzaShop中
IPizza pizza = createPizza(type);
if(pizza != null){
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}
return pizza;
}
// 抽象的“工厂方法”
protected abstract IPizza createPizza(String type);
}
// 每个子类都要继承PizzaShop
public class BeijingPizzaShop extends PizzaShop{
// 实现抽象的“工厂方法”
protected IPizza createPizza(String type) {
if(type == null){
System.out.println("BeijingPizzaShop:What kind of pizza do you want?");
return null;
}
IPizza pizza = null;
if(type.equals("cheese")){
pizza = new BeijingPizzaCheese();
}else if(type.equals("fruit")){
pizza = new BeijingPizzaFruit();
}else if(type.equals("banana")){
pizza = new BeijingPizzaBanana();
}
return pizza;
}
}
public class ShenZhenPizzaShop extends PizzaShop{
protected IPizza createPizza(String type) {
if(type == null){
System.out.println("ShenZhenPizzaShop kind of pizza do you want?");
return null;
}
IPizza pizza = null;
if(type.equals("cheese")){
pizza = new ShenZhenPizzaCheese();
}else if(type.equals("fruit")){
pizza = new ShenZhenPizzaFruit();
}else if(type.equals("banana")){
pizza = new ShenZhenPizzaBanana();
}
return pizza;
}
}
2.进一步说明:
(1)做到了解耦--orderPizza()是在PizzaShop中定义的,但是他在使用createPizza()创建的pizza对象类执行prepare、bake、cut、box方法时并不知道具体的pizza对象是哪种类型。
(2)pizza对象的具体类型仅由具体的pizza店(顾客)决定。
3.有关工厂方法
(1)简单工厂是有一个专职对象负责所有具体类的实例化,而工厂方法则是由一群子类来负责实例化;
(2)将一个orderpizza方法和一个工厂方法联合起来,可以成为一个框架;
(3)工厂方法将生产知识封装进各个创建者,这种做法也可视为一个框架;
4.定义工厂方法模式
(1)工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
转载于:https://blog.51cto.com/wangzhaoli/1763759