单例模式是我最初认识的设计模式,工厂模式呢是我最初使用的设计模式。
工厂模式分为三种:简单工厂模式,工厂模式,抽象工厂模式
以前一直不清楚这三种工厂模式的区别,在系统的学习后终于明白了。
简单工厂模式:其实也不算设计模式,它更像是一种编程习惯。只是多了一个工厂类来实例化产品对象,客户类并不需要知道具体调用哪个产品类,只需要调用工厂类去实例化产品对象就好。
工厂模式:定义一个创建对象的接口,有子类确定实例化的类是哪一个,工厂模式让类把实例化推迟给子类。
抽象工厂模式:用于创建一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
强行理解概念很容易绕晕自己,就简单的举个例子吧:
比如你要开一家披萨店,里面有芝士披萨、海鲜披萨等,这个时候可以使用简单工厂模式:写一个工厂类去实例化产品类,即一个披萨工厂类实例化各种口味的披萨;
如果你要开两家披萨店,一家是纽约风味,一家是芝加哥风味的,这个时候可以使用工厂模式:一个是纽约披萨工厂类,一个是芝加哥披萨工厂类。工厂模式与简单工厂模式的不同是:工厂模式抽象出工厂类,可以有多个工厂继承抽象工厂类。
当你需要统一管理披萨的原材料,例如披萨面饼、酱料等,可以使用抽象工厂模式:面饼工厂类,实例化纽约披萨面饼、芝加哥披萨面饼,抽象工厂类与工厂类的不同是:抽象工厂实例化的产品类依赖于工厂类的产品类,比如,抽象工厂的面饼工厂类可以做纽约披萨面饼、芝加哥披萨面饼,这取决于披萨的需要。
(披萨的例子参考《Head First设计模式》这本书,下面的例子参考《Java与模式》这本书)
再简单的说个例子,如果你现在有一个小农场,里面种各种蔬菜,这个时候可以使用简单工厂模式:一个工厂类管理各种蔬菜;
你的农场开始扩建,种有各种蔬菜还有各种水果,这个时候可以使用工厂模式:一个蔬菜工厂类,一个水果工厂类;
现在你的农场越做越大,引入了热带水果以及热带蔬菜,这个时候就可以使用抽象工厂模式了。
好了,以下开始贴代码,首先是简单工厂的示例代码,第二部分是工厂模式的示例代码,最后是抽象工厂模式的示例代码。
简单工厂模式
先抽象出披萨类:
public abstract class Pizza {
String name;
String dough;
String sauce;
List<String> toppings = new ArrayList<>();
abstract void prepare();
void bake() {
System.out.println("\n烘焙25-30min");
}
void cut() {
System.out.println("将披萨切块");
}
void box() {
System.out.println("将披萨装盒");
}
public String getName() {
return name;
}
}
纽约芝士披萨:
public class NYStyleCheesePizza extends Pizza {
public NYStyleCheesePizza() {
name = "纽约风味芝士披萨";
dough = "纽约厚面饼";
sauce = "纽约海鲜酱料";
toppings.add("纽约风味--芝士");
}
@Override
void prepare() {
System.out.println("\n======================");
System.out.println(name);
System.out.println("制作:");
System.out.println(" " + dough);
System.out.println(" " + sauce);
System.out.println(" 调味品:");
for (int i = 0; i < toppings.size(); i++) {
System.out.println(" " + toppings.get(i));
}
}
}
纽约海鲜披萨:
public class NYStyleClamPizza extends Pizza {
public NYStyleClamPizza() {
name = "纽约风味海鲜披萨";
dough = "纽约厚面饼";
sauce = "纽约酱料";
toppings.add("纽约风味--海鲜");
}
@Override
void prepare() {
System.out.println("\n======================");
System.out.println(name);
System.out.println("制作:");
System.out.println(" " + dough);
System.out.println(" " + sauce);
System.out.println(" 调料:");
for (int i = 0; i < toppings.size(); i++) {
System.out.println(" " + toppings.get(i));
}
}
}
最重要的工厂类:
public class PizzaStore {
public Pizza orderPizza(String type) {
Pizza pizza;
pizza = creatPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
public Pizza creatPizza(String type) {
if ("cheese".equals(type)) {
return new NYStyleCheesePizza();
} else if ("clam".equals(type)) {
return new NYStyleClamPizza();
}
return null;
}
}
开始测试吧~
public class Test {
public static void main(String[] args) {
PizzaStore store = new PizzaStore();
Pizza pizza = store.orderPizza("cheese");
System.out.println("一号客人收到" + pizza.getName());
Pizza pizza2 = store.orderPizza("clam");
System.out.println("二号客人收到" + pizza2.getName());
}
}
结果:
工厂模式
纽约披萨店的披萨与上面代码差不多,此处只贴芝加哥披萨店的披萨(芝加哥海鲜披萨):
public class ChicagoStyleClamPizza extends Pizza {
public ChicagoStyleClamPizza() {
name = "芝加哥风味海鲜披萨";
dough = "芝加哥薄面饼";
sauce = "芝加哥海鲜酱料";
toppings.add("芝加哥风味--海鲜");
}
void cut() {
System.out.println("芝加哥披萨切成正方形");
}
@Override
void prepare() {
System.out.println("\n======================");
System.out.println(name);
System.out.println("制作:");
System.out.println(" " + dough);
System.out.println(" " + sauce);
System.out.println(" 调料:");
for (int i = 0; i < toppings.size(); i++) {
System.out.println(" " + toppings.get(i));
}
}
}
披萨工厂抽象类:
public abstract class PizzaStore {
public Pizza orderPizza(String type) {
Pizza pizza;
pizza = creatPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
abstract Pizza creatPizza(String type);
}
纽约披萨工厂类:
public class NYPizzaFactory extends PizzaStore {
@Override
Pizza creatPizza(String type) {
if ("cheese".equals(type)) {
return new NYStyleCheesePizza();
}else if("clam".equals(type)){
return new NYStyleClamPizza();
}
return null;
}
}
芝加哥披萨工厂与纽约披萨工厂类类似,此处直接贴测试结果:
抽象工厂模式
对披萨类只做了小部分改动,引入披萨原料类:
public abstract class Pizza {
String name;
Dough dough;
Sauce sauce;
List<String> toppings = new ArrayList<>();
abstract void prepare();
void bake() {
System.out.println("烘焙25-30min");
}
void cut() {
System.out.println("将披萨切块");
}
void box() {
System.out.println("将披萨装盒");
}
public String getName() {
return name;
}
}
纽约芝士披萨:
public class NYStyleCheesePizza extends Pizza {
PizzaIngredientFactory ingredient;
public NYStyleCheesePizza(PizzaIngredientFactory ingredient) {
name = "纽约风味芝士披萨";
toppings.add("纽约风味--芝士");
this.ingredient = ingredient;
}
@Override
void prepare() {
System.out.println("======================");
System.out.println(name);
dough = ingredient.creatDouge();
sauce = ingredient.creatSauce();
System.out.println(" 调味品:");
for (int i = 0; i < toppings.size(); i++) {
System.out.println(" " + toppings.get(i));
}
}
}
接下来是披萨原料工厂类,因为酱料与面饼类似,就只写面饼的代码吧
面饼抽象类:
public abstract class Dough {
String name;
public String getName() {
return name;
}
}
纽约厚面饼:
public class NYDough extends Dough {
public NYDough() {
name = " 纽约面饼...";
System.out.println(name);
}
}
披萨原料工厂接口:
public interface PizzaIngredientFactory {
Dough creatDouge();
Sauce creatSauce();
}
纽约披萨原料工厂:
public class NYPizzaIngredientFactory implements PizzaIngredientFactory {
@Override
public Dough creatDouge() {
return new NYDough();
}
@Override
public Sauce creatSauce() {
return new NYSauce();
}
}
测试结果:
以上完整代码可以在http://download.csdn.net/download/sjm01234/10200158下载( ˃ᴗ˂ )