简单工厂遇到的问题
在《简单工厂模式》中利用了披萨实例介绍了简单工厂模式。在简单工厂模式中如果想开设多个披萨店。每个披萨店的制作方式和披萨种类都不一样。如果还是在Factory类中添加新的产品,就会操作Factory的复杂性。也不好定制不同披萨店的制作方式。这个时候如果还使用简单工厂模式,因为简单工厂模式是将披萨的制作流程完全承包了。
解决方案
可以这么解决。将制作披萨的方式交由各个披萨店执行,披萨的订单还是给披萨店自己处理。也就是说将Factory类中的createPizza声明为一个接口。子类负责createPizza实现,其他部分还是保持不变。
基本定义
工厂方法定义了一个创建对象的接口。由子类决定要怎么构建那些种类的产品。工厂方法模式让构建实例的方式下方到了子类当中
模式结构
Concrete:具体
ConcreteProduct 具体产品
Creator:创作者
ConcreteCreator:具体创作者
-
Product :抽象产品。所有的产品必须实现这个共同的接口,这样一来 ,使用这些产品的类既可以引用这个接口。而不是具体。
-
ConcreteProduct :具体产品。
-
Creator :抽象工厂。它实现了所有操纵产品的方法,但不实现工厂方法Creator所有的子类都必须要实现factoryMethod()方法。
-
ConcreteCreator:具体工厂。制造产品的实际工厂。它负责创建一个或者多个具体产品,只有ConcreteCreator类知道如何创建这些产品。(与简单工厂模式的区别在:我们的工厂模式是面向接口编程的,动态工厂模式)
模式实现
工厂模式是简单工厂模式的一种延伸。在工厂模式中工厂类不负责产品的构建。而是将创建工作交个子类完成。也就是说核心工厂类只提供一个接口,具体实现交个集成他的子类完成。当我们系统要增加其他新的对象时。我们只需要添加一些产品的种类,和它创建的工厂即可。不需要对原本工厂进行任何改变。很好的复合了“开闭原则”
类图
![](https://img.haomeiwen.com/i15928496/573fddf7925bb309.png)
代码
/**
* 抽象工厂类,也是我们工厂设计模式的一个核心思想类(面向接口编程)
*/
public interface Factory{
Pizza createPizza(String typePizza);
}
/**
* 抽象产品类,作为父类出现,提供给中pizza种类继承
*/
public abstract class Pizza {
/**
* prepare 准备 把…预备好;
*/
public abstract void prepare();
/**
* make 制作
*/
public abstract void make();
/**
* complete 完成
*/
public abstract void complete();
}
/**
* 肉类披萨
*/
public class PizzaMeet extends Pizza {
public void prepare() {
System.out.println("准备肉类");
}
public void make() {
System.out.println("开始制作肉类披萨");
}
public void complete() {
System.out.println("肉类披萨制作成功");
}
}
/**
* 蔬菜披萨
*/
public class PizzaVegg extends Pizza {
public void prepare() {
System.out.println("准备蔬菜");
}
public void make() {
System.out.println("开始制作蔬菜披萨");
}
public void complete() {
System.out.println("蔬菜披萨制作成功");
}
}
/**
* Store 商店
*/
public class PizzaStore1 implements Factory {
/**
* 现在来看,我们的这个店面,不管有多少pizza,都是由自己进行控制的,如果该店面增加了产品产品种类,只需要修改自己的
* pizza店的代码就可以了,而不会影响其他店的正常运行
*
* @param typePizza
* @return
*/
@Override
public Pizza createPizza(String typePizza) {
if ("MEET".equals(typePizza)) {
return new PizzaMeet();
} else {
return null;
}
}
public void orderPizza(String typePizza) {
System.out.println("客户开始预定pizza...披萨类型" + typePizza);
Pizza pizza = createPizza(typePizza);
pizza.prepare();
pizza.make();
pizza.complete();
System.out.println("披萨制作完成");
}
public static void main(String[] args) {
PizzaStore1 pizzaStore1 = new PizzaStore1();
pizzaStore1.orderPizza("MEET");
}
}
// 输出结果
客户开始预定pizza...披萨类型MEET
准备肉类
开始制作肉类披萨
肉类披萨制作成功
披萨制作完成
/**
* 如果要新增pizza商店,我们只需要实现factory就可以了,不需要修改factory类
* 如果我新增加分店的话,我不会影响其他店的正常开设,我只关心我目前所开店面的代码。
* Store 商店
*/
public class PizzaStore2 implements Factory{
@Override
public Pizza createPizza(String typePizza){
if ("VGGE".equals(typePizza)) {
return new PizzaVegg();
} else {
return null;
}
}
public void orderPizza(String typePizza) {
System.out.println("客户开始预定pizza...披萨类型" + typePizza);
Pizza pizza = createPizza(typePizza);
pizza.prepare();
pizza.make();
pizza.complete();
System.out.println("披萨制作完成");
}
public static void main(String[] args) {
PizzaStore2 pizzaStore2 = new PizzaStore2();
pizzaStore2.orderPizza("VGGE");
}
}
优缺点
优点
- 见工厂模式当中。用户只需要知道产品对应的工厂即可。不需要关注创建产品的细节。
- 每当需要添加新的产品种类时,只需要添加对应的产品和构建工厂即可,不需要对原本的工厂进行改变。符合“开闭原则”
缺点
- 每次添加产品是都需要添加对应的工厂。使系统中类的个数增加,在一定程度上增加了系统的复杂性
总结
1、工广方法模式完全符合“开闭原则”。
2、工厂方法模式使用继承或者实现,将对象的创建委托给子类,通过子类实现工厂方法来创建对象
3、工厂方法允许类将实例化延伸到子类进行。
4、在工厂方法模式中,创建者通常会包含依赖于抽象产品的代码,而这些抽象产品是、由子类创建的,创建者不需要真的知道在制作哪种具体产品。
网友评论