转载

设计模式干货系列:(一)简单工厂模式

面对设计模式这个高大上的敌人,如何找到一个脆弱可以下手的地方尤其重要,经过参考《JAVA与模式》后发现最容易下手但又及其重要的模式,那就是简单工厂模式,书里是这么介绍的:简单工程模式是最简单的模式,有助于引出工厂方法模式,而方法工厂模式在后面的许多模式都有应用,它在模式的讨论里屡见不鲜。了解工厂方法模式是了解所有模式的起点。看了这段话,我热血澎湃,这么脆弱又及其重要的模式不打你打谁。

正文

介绍简单工厂模式之前先通过一个披萨项目的例子来引出问题,然后给出简单工厂模式这种解决方案,然后随着披萨项目的不断扩展,遇到新的问题,引出工厂方法模式,然后又遇到新的问题,引出最终解决方案,抽象工厂模式。

披萨项目介绍

客人来披萨店点披萨,点了某种披萨,我们在后台要准备原料,烘培,切割,打包这几个步骤,最后给用户吃。把上述这个过程抽象后,设计如下:

设计模式干货系列:(一)简单工厂模式

Pizza 这个抽象类,里面有 prePare , bake , cut , box 这4个方法,其中因为不同的披萨原料不一样,这里 prePare 当成抽象方法,剩下三个都设定成具体化。在继承的时候,每一种披萨( GreekPizza 或者 CheesePizza )具体实例化这个 prepare 方法。根据用户选择的披萨,用 if...else 来生成不同的披萨给用户。

代码如下:

Pizza披萨抽象类:

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+" 准备材料中~");
}
}

OrderPizza订单类:

/**
* 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 "";
}
}
}

PizzaStroe披萨店类:

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 )角色:工厂方法模式所创建的任务对象都是这个角色的实例,这里指 GreekPizzaCheesePizza

把上面的披萨项目用简单工厂模式来现实的话,无非就是创建一个工厂类来代替服务员之前要准备披萨材料的操作,而服务员只要告诉这个工厂类他需要哪种披萨就好。

代码示例讲解:

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公众号,开源开源,有需求的可以关注~撒花

设计模式干货系列:(一)简单工厂模式
原文  http://tengj.top/2016/04/02/sjms1simpleFactory/
正文到此结束
Loading...