在我平常的工作中我们往往会写下如下的代码。
以上代码的问题在于我们要增加种类的时候,需要打开这段代码进行修改。这样造成系统难以维护,也更容易犯错。
我们对拓展开放,对修改关闭。通常这种情况下,应该抽象出变化的部分。
2.如何实现工厂模式。
- 我们首先实现一个简单工厂模式
抽象出变化的部分,就是工厂
1234567891011public class SimplePIizzaFactory {public Pizza createPizza(String type) {Pizza pizza = null;if (type.equals("ChessPizza")) {pizza = new ChessPizza();} else if (type.equals("CalmPizza")) {pizza = new CalmPizza();}return pizza;}}调用的时候只需要用简单工厂生成就行
12345678910111213public class PizzaStroe {SimplePIizzaFactory simplePIizzaFactory;public PizzaStroe(SimplePIizzaFactory simplePIizzaFactory) {this.simplePIizzaFactory = simplePIizzaFactory;}public Pizza orderPizza(String type) {Pizza pizza =simplePIizzaFactory.createPizza(type);pizza.bake();return pizza;}}
上面这样做的好处在于抽象出变化的部分,供其他部分调用 。另外,当我们需要修改的时候,只需要修改工厂类,其他的部分就不需要变动。
- 工厂模式(真正意义上的工厂模式)
工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
- 定义一个基本的工厂基类和它的子工厂类12345678910111213141516171819202122232425262728293031323334//定义抽象的Pizza类public abstract class Pizza {public String name;public ArrayList<String> ingredent=new ArrayList<>();void prepare(){System.out.println("Prepare: "+name);for(int i=0;i<ingredent.size();i++){System.out.print(ingredent.get(i)+" ");}}void bake(){System.out.println("Pizza is baking");}public String getName() {return name;}public void setName(String name) {this.name = name;}public ArrayList<String> getIngredent() {return ingredent;}public void setIngredent(ArrayList<String> ingredent) {this.ingredent = ingredent;}}
|
|
- 当我们需要Pizza的时候,只需要用那个工厂类就可以构造出那种风格的Pizza1234567891011public class PizzaTest {public static void main(String[] args) {PizzaStroe beijingPizzaStore=new BeijingPizzaStore();PizzaStroe wuhanPizzaStore=new WuhanPizzaStore();Pizza pizza1=beijingPizzaStore.orderPizza("CalmPizza");Pizza pizza2=wuhanPizzaStore.orderPizza("CalmPizza");System.out.println(pizza1.getName());System.out.println(pizza2.getName());}}
来看下类图的关系
简单工厂与工厂方法的区别:简单工厂把全部的事情在一个地方都处理完了,然而工厂方法却是创建一个框架,让子类决定如何实现。
简单工厂的做法,可以将对象的创建封装起来,但是简单工厂不具备工厂方法的弹性,因为简单工厂不能变更正在创建的产品。
- 抽象工厂模式
首先给出定义抽象工厂模式 提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类
- 首先我们定义抽象接口1234public interface PropertyFactory {public String getName();public ArrayList<String> getIngredent();}
在实际的场合中,抽象接口里面的抽象方法都是返回某个想要创建的抽象类,我这里比较简单,直接返回字符串和集合。之所以称为抽象工厂,我们从这里就可以看出来。通过抽象的方法,返回你希望得到的类的基类。
- 我们构造抽象工厂类的实现类12345678910111213141516171819202122232425262728public class CalmPropertyFactory implements PropertyFactory {public String getName() {return "NewCalmPizza";}public ArrayList<String> getIngredent() {ArrayList<String> arrayList=new ArrayList<>();arrayList.add("Newcalm");return arrayList;}}public class ChessPropertyFactory implements PropertyFactory {public String getName() {return "NewChessPizza";}public ArrayList<String> getIngredent() {ArrayList<String> arrayList = new ArrayList<>();arrayList.add("Newchess");return arrayList;}}
那么此时的Pizza的子类应该如此构造
直接用对应的原料工厂来构造。
来看下类图。
- 个人总结(conclusion)
通过以上的描述,我们很容易明白工厂模式,也很容易区分简单工厂和工厂模式的区别(即构造类是在一个工厂类里面统一构造,还是通过子类的工厂方法来构造)。但是令人迷惑的是工厂模式与抽象工厂模式有什么区别。区别如下:抽象工厂的每个方法实际上看起来都像是工厂方法,每个方法都被声明成抽象。而子类的方法来覆盖这些方法来创建某些对象。注意到,这里的子类是想要构造类的成分,就像我上面的写的name和ingredent成员。Pizza的子类只需要依赖依赖这些成分工厂类,例如ChessPropertyFactory ,就能构造出对象。重点突出抽象,是因为它有一个总的抽象接口,实现它的子类负责构造对象的成分,总而构成对象。