面对设计模式这个高大上的敌人,如何找到一个脆弱可以下手的地方尤其重要,经过参考《JAVA与模式》后发现最容易下手但又及其重要的模式,那就是简单工厂模式,书里是这么介绍的:简单工程模式是最简单的模式,有助于引出工厂方法模式,而方法工厂模式在后面的许多模式都有应用,它在模式的讨论里屡见不鲜。了解工厂方法模式是了解所有模式的起点。看了这段话,我热血澎湃,这么脆弱又及其重要的模式不打你打谁。
介绍简单工厂模式之前先通过一个披萨项目的例子来引出问题,然后给出简单工厂模式这种解决方案,然后随着披萨项目的不断扩展,遇到新的问题,引出工厂方法模式,然后又遇到新的问题,引出最终解决方案,抽象工厂模式。
客人来披萨店点披萨,点了某种披萨,我们在后台要准备原料,烘培,切割,打包这几个步骤,最后给用户吃。把上述这个过程抽象后,设计如下:
Pizza
这个抽象类,里面有 prePare
, bake
, cut
, box
这4个方法,其中因为不同的披萨原料不一样,这里 prePare
当成抽象方法,剩下三个都设定成具体化。在继承的时候,每一种披萨( GreekPizza
或者 CheesePizza
)具体实例化这个 prepare
方法。根据用户选择的披萨,用 if...else
来生成不同的披萨给用户。
代码如下:
public abstract class Pizza {
protected String name;
public abstract void prepare();
public void bake(){
System.out.println(name+" 正在烤~");
}
public void cut(){
System.out.println(name+" 正在切~");
}
public void box(){
System.out.println(name+" 正在打包~");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
```
**GreekPizza披萨类**:
``` java
public class GreekPizza extends Pizza{
@Override
public void prepare() {
super.setName("GreekPizza");
System.out.println(name+" 准备材料中~");
}
}
```
**CheesePizza披萨类**:
``` java
public class CheesePizza extends Pizza{
@Override
public void prepare() {
super.setName("CheesePizza");
System.out.println(name+" 准备材料中~");
}
}
/**
* Created by tengj on 2016/4/1.
*/
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 {
break;
}
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
} while (true);
}
/**
* 获取用户输入
* @return
*/
private String gettype() {
try {
BufferedReader strin = new BufferedReader(new InputStreamReader(
System.in));
System.out.println("input pizza type:");
String str = strin.readLine();
return str;
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
}
public class PizzaStroe {
public static void main(String[] args) {
OrderPizza mOrderPizza;
mOrderPizza=new OrderPizza();
}
}
业务很简答,根据用户想买的披萨,生成不同的披萨,具体调试输出如下:
input pizza type: cheese CheesePizza 准备材料中~ CheesePizza 正在烤~ CheesePizza 正在切~ CheesePizza 正在打包~ input pizza type: greek GreekPizza 准备材料中~ GreekPizza 正在烤~ GreekPizza 正在切~ GreekPizza 正在打包~
传统的设置这样也没错,如果业务发展,会造成什么问题呢?
现在如果多了一种口味 qiaokeliPizza
,正常办法是生成一个 QiaokeliPizza
类,继承于 Pizza
,然后在 OrderPizza
中,添加
else if (ordertype.equals("qiaokeli")){
pizza = new QiaokeliPizza();
}
如果后来披萨口味越来越多,负责点餐的服务员会很不开心的,因为就目前来说,准备披萨材料是在他的订单类里面处理的,如果万一客人点的披萨太多,而他准备错了材料,那就得他来负责。他在想,为什么我不能只负责点餐,准备材料这么重要的事情让别人来搞定呢?这样出问题了也跟他没关系。他所想的解决方案,简单工厂模式就可以做到。
简单工厂模式是类的创建模式,又叫做静态工厂方法( Static Factory Method
)模式。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。
简单工厂模式的结构如下:
从图中可以看出,简单工厂模式涉及到工厂角色,抽象产品角色以及具体产品角色等三个角色:
Factory
)角色:担任这个角色的是工厂方法模式的核心,含有与应用紧密相关的商业逻辑。 Product
)角色:担任这个角色的类是由工厂方法模式所创建的对象的父类,或它们共同拥有的接口,这里指的就是 Pizza
这个类。 Concrete Product
)角色:工厂方法模式所创建的任务对象都是这个角色的实例,这里指 GreekPizza
和 CheesePizza
。 把上面的披萨项目用简单工厂模式来现实的话,无非就是创建一个工厂类来代替服务员之前要准备披萨材料的操作,而服务员只要告诉这个工厂类他需要哪种披萨就好。
代码示例讲解:
SimplePizzaFactory
简单工厂类,根据的参数来准备不同的披萨材料:
public class SimplePizzaFactory {
public static Pizza CreatePizza(String orderType){
Pizza pizza = null;
if (orderType.equals("cheese")) {
pizza = new CheesePizza();
} else if (orderType.equals("greek")) {
pizza = new GreekPizza();
}
return pizza;
}
}
OrderPizza
订单类中,服务员只需要调用工厂类 SimplePizzaFactory
的静态方法 CreatePizza()
即可:
public class OrderPizza {
public OrderPizza() {
setFactory();
}
public void setFactory(){
Pizza pizza = null;
String ordertype;
do {
ordertype = gettype();
//pizza由工厂类simplePizzaFactory来生成,后续有新增披萨种类也只在simplePizzaFactory类中改动
pizza=SimplePizzaFactory.CreatePizza(ordertype);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
} while (true);
}
/**
* 获取用户输入
* @return
*/
private String gettype() {
try {
BufferedReader strin = new BufferedReader(new InputStreamReader(
System.in));
System.out.println("input pizza type:");
String str = strin.readLine();
return str;
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
}
PizzaStroe
披萨店类:
public class PizzaStroe {
public static void main(String[] args) {
OrderPizza mOrderPizza=null;
mOrderPizza=new OrderPizza(new SimplePizzaFactory());
}
}</pre>
这样设计后,服务员就轻松多了,主要负责告诉工程类需要什么类型的披萨就可以,终于不要担心搞错了而被扣工资了。
上面用披萨项目的列子来讲解了简单工厂模式的使用,总结下优缺点:
简单工厂模式的优点:
模式的核心是工厂类。这个类含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例。而客户端则可以免除直接创建对象的责任(比如那个服务员)。简单工厂模式通过这种做法实现了对责任的分割。
简单工厂模式的缺点:
这个工厂类集中了所以的创建逻辑,当有复杂的多层次等级结构时,所有的业务逻辑都在这个工厂类中实现。什么时候它不能工作了,整个系统都会受到影响。并且简单工厂模式违背了 开闭原则 (对扩展的开放,对修改的关闭)。
最近撸了个java的公众号,学习资源超级多,视频,电子书,最新开发工具一个都不能少,已全部分享到百度云盘,求资源共享,打造一个学习方便,工作方便的java公众号,开源开源,有需求的可以关注~撒花