1. 程式人生 > >設計模式之工廠模式---物件的例項化部分提取出來---三種不同的提取方法

設計模式之工廠模式---物件的例項化部分提取出來---三種不同的提取方法

一、不使用工廠

披薩專案:要方便披薩品種的擴充套件、要便於維護、要能執行時擴充套件

披薩族的設計:
抽象Pizza類,有四個方法:prepare()、bake(),cut(),box()

實際的披薩:GreekPizza和CheesePizza

披薩工廠設計:if…else … if …else

1、抽象Pizza類

package com.java.jikexueyuan.pizzastore.pizza;

public abstract class Pizza {
	protected String name;
	
	public abstract void prepare();
	
	public void bake()
	{
		System.out.println(name+" baking;");
	}
	public void cut()
	{
		System.out.println(name+" cutting;");
	}
	public void box()
	{
		System.out.println(name+" boxing;");
	}
	public void setname(String name)
	{
		this.name=name;
	}
}

2、實際的披薩類

1)、CheesePizza

package com.java.jikexueyuan.pizzastore.pizza;

public class CheesePizza extends Pizza {

	@Override
	public void prepare() {
		// TODO Auto-generated method stub
		super.setname("CheesePizza");
		
		System.out.println(name+" preparing;");
	}

}

2)、GreekPizza

package com.java.jikexueyuan.pizzastore.pizza;

public class GreekPizza extends Pizza {

	@Override
	public void prepare() {
		// TODO Auto-generated method stub
		super.setname("GreekPizza");
		
		System.out.println(name+" preparing;");
	}

}

3、一般OrderPizza實現類

package com.java.jikexueyuan.pizzastore;

public class OrderPizza {

	public OrderPizza() {
		Pizza pizza = null;
		String ordertype;
		
		do {
			ordertype = gettype();   //控制檯輸入
			
			if (ordertype.equals("cheese")) {
				pizza = new CheesePizza();
			} else if (ordertype.equals("greek")) {
				pizza = new GreekPizza();
			} else if (ordertype.equals("pepper")) {
				pizza = new PepperPizza();
			} else if (ordertype.equals("chinese")) {
				pizza = new ChinesePizza();
			} else {
				break;
			}
			pizza.prepare();
			pizza.bake();
			pizza.cut();
			pizza.box();
		} while (true);
	}
}

簡單工廠總結:如果要擴充套件新的pizza,就要將OrderPizza這個簡單工廠停下來修改其中程式碼。

4、怎麼改進呢?

將變化的地方抽取出來,使用簡單工廠來封裝,這樣就不用停止orderPizza的執行,如下:

二、簡單工廠(從主類提取例項化(變化)部分)

定義一個例項化披薩物件的類,封裝建立物件的程式碼

1、SimplePizzaFactory類

public class SimplePizzaFactory {

	public Pizza CreatePizza(String ordertype) {
		Pizza pizza = null;

		if (ordertype.equals("cheese")) {
			pizza = new CheesePizza();
		} else if (ordertype.equals("greek")) {
			pizza = new GreekPizza();
		} else if (ordertype.equals("pepper")) {
			pizza = new PepperPizza();
		}
		return pizza;

	}

}

2、新的OrderPizza類

public class OrderPizza {
	SimplePizzaFactory mSimplePizzaFactory;

	public OrderPizza(SimplePizzaFactory mSimplePizzaFactory) {
		setFactory(mSimplePizzaFactory);
	}

	public void setFactory(SimplePizzaFactory mSimplePizzaFactory) {
		Pizza pizza = null;
		String ordertype;

		this.mSimplePizzaFactory = mSimplePizzaFactory;

		do {
			ordertype = gettype();
			pizza = mSimplePizzaFactory.CreatePizza(ordertype);
			if (pizza != null) {
				pizza.prepare();
				pizza.bake();
				pizza.cut();
				pizza.box();
			}

		} while (true);

	}

三、工廠方法模式

將物件的例項化推遲到子類

困惑:披薩專案加盟店
解決:將披薩物件例項化功能抽象成抽象方法,在不同加盟店具體實現功能;

1、抽象的OrderPizza

package com.java.jikexueyuan.pizzastore.method;

public abstract class OrderPizza {

	public OrderPizza() {
		Pizza pizza = null;
		String ordertype;

		do {
			ordertype = gettype();
			pizza = createPizza(ordertype);

			pizza.prepare();
			pizza.bake();
			pizza.cut();
			pizza.box();
		} while (true);
	}

    // 方法抽象出來
	abstract Pizza createPizza(String ordertype);
}

2、實際的OrderPizza

1)、紐約的NYOrderPizza

package com.java.jikexueyuan.pizzastore.method;

public class NYOrderPizza extends OrderPizza {

	@Override
	Pizza createPizza(String ordertype) {
		Pizza pizza = null;

		if (ordertype.equals("cheese")) {
			pizza = new NYCheesePizza();
		} else if (ordertype.equals("pepper")) {
			pizza = new NYPepperPizza();
		}
		return pizza;

	}

}

2)、倫敦的LDOrderPizza

public class LDOrderPizza extends OrderPizza {

	@Override
	Pizza createPizza(String ordertype) {
		Pizza pizza = null;

		if (ordertype.equals("cheese")) {
			pizza = new LDCheesePizza();
		} else if (ordertype.equals("pepper")) {
			pizza = new LDPepperPizza();
		}
		return pizza;

	}

}

四、抽象工廠模式

定義一個介面,用於建立相關或有依賴關係的物件族,而無需明確指定具體類。

1、抽象AbsFactory類

package com.java.jikexueyuan.pizzastore.absfactory;

public interface AbsFactory {
	public Pizza CreatePizza(String ordertype) ;
}

2、具體實現類

1)、倫敦LDFactory

package com.java.jikexueyuan.pizzastore.absfactory;

public class LDFactory implements AbsFactory {

	@Override
	public Pizza CreatePizza(String ordertype) {
		Pizza pizza = null;

		if (ordertype.equals("cheese")) {
			pizza = new LDCheesePizza();
		} else if (ordertype.equals("pepper")) {
			pizza = new LDPepperPizza();
		}
		return pizza;
	}
}

2)紐約NYFactory

package com.java.jikexueyuan.pizzastore.absfactory;

public class NYFactory implements AbsFactory {

	@Override
	public Pizza CreatePizza(String ordertype) {
		Pizza pizza = null;

		if (ordertype.equals("cheese")) {
			pizza = new NYCheesePizza();
		} else if (ordertype.equals("pepper")) {
			pizza = new NYPepperPizza();
		}
		return pizza;
	}
}

3、OrderPizza類(AbsFactory的具體工廠傳進來建立pizza物件)

package com.java.jikexueyuan.pizzastore.absfactory;

public class OrderPizza {
	AbsFactory mFactory;

	public OrderPizza(AbsFactory mFactory) {
		setFactory(mFactory);
	}

	public void setFactory(AbsFactory mFactory) {
		Pizza pizza = null;
		String ordertype;

		this.mFactory = mFactory;

		do {
			ordertype = gettype();
			pizza = mFactory.CreatePizza(ordertype);
			if (pizza != null) {
				pizza.prepare();
				pizza.bake();
				pizza.cut();
				pizza.box();
			}
		} while (true);
	}
}

五、依賴抽象原則

1、變數不要持有具體類的引用

例如,OrderPizza類中建立披薩的變數;

2、不要讓類繼承自具體類,要繼承自抽象類或介面

3、不要覆蓋類中已實現的方法