概述:
工厂模式可分为3小类:
简单工厂、工厂方法、抽象工厂
-
简单工厂
直接上例子:
public class Test {
public static void main(String[] args) {
int code;
Duck duck;
if(code == 1){
duck = new DuckCall();
}else if(code == 2){
duck = new RubberDuck();
}else if(code == 3){
duck = new MallardDuck();
}else{
duck = new RedHeadDuck();
}
}
}
以上ifelse 的部分,会随着鸭子的种类变化面临增删
也会随着客户需求在不同的code下创建另一种Duck
根据封装变化
得到简单工厂
class SimpleDuckFactory{
public Duck create(int code){
Duck duck;
if(code == 1){
duck = new DuckCall();
}else if(code == 2){
duck = new RubberDuck();
}else if(code == 3){
duck = new MallardDuck();
}else{
duck = new RedHeadDuck();
}
return duck;
}
}
这种将创建对象的代码移动到另一个类中,称作简单工厂
优势:
1》一个工厂被提取出来后,就可以“摆脱”原来的单个客户,面向多个客户
2》而且修改的时候,也只要修改这个简单工厂类即可
-
工厂方法
上类图(这次是Pizza店)
父类Pizza是一个abstract类,其中createPizza()是一个虚拟方法,需要子类实现
上代码:
父类:
public abstract class PizzaStore {
Pizza order(){
int type = 0;
Pizza pizza = createPizza(type);
pizza.prepare();
return pizza;
}
abstract Pizza createPizza(int type);
}
子类:
public class NanjingPizzaStore extends PizzaStore{
Pizza createPizza(){
//这里可以加入if else来进行扩展,如下第二个
return new NanjingPizza();
}
Pizza createPizza(int type){
Pizza pizza;
switch(type){
case 1:
//仔鸡味
break;
case 2:
//咖喱味
break;
case 3:
//番茄味
break;
default:
//断货了
break;
}
return pizza;
}
}
给出定义:
定义了一个创建对象的接口,但是有子类决定具体实例化哪个类,工厂方法让类把实例化操作推迟到子类
注意:
从上面的例子应该也可以看出,所谓的子类决定实例化哪一个Pizza,其实是通过父类的披萨店运行时选择具体实现子类(例如:NanjingPizzaStore)来实现“动态”修改的效果。并不是子类在运行时决定,其实子类new哪个,是在代码中写死的(非动态)
-
抽象工厂
设计原则5:
理解:为啥叫依赖倒置,拿本文中的例子来解释,你要创建一个Pizza店,首先是自上而下的思路来创建你的类框架,现在采取倒置思维,自下而上思考,总结下层依赖抽象成接口,这样就是“尽量多依赖抽象,少依赖具体类”啦
抽象工厂理解:简单工厂+工厂方法的组合
上类图:
首先用简单工厂,将new的代码从上层类中抠出来,并对这个“变化”部分进行抽象,这时候在采用工厂方法来实现这个框架的剩余部分
上代码(这里以Pizza店为例):
抽象出一个Pizza的接口:
public abstract class Pizza {
abstract String getDescription();
}
Pizza子类(虽然都是咖喱Pizza,但是上海的店和南京的店做出来的是口味不同的):
public class NanjingCurryPizza extends Pizza{
@Override
String getDescription() {
return "南京咖喱味Pizza";
}
}
public class ShanghaiCurryPizza extends Pizza{
@Override
String getDescription() {
return "上海咖喱味Pizza";
}
}
新建Pizza店:
public class PizzaStore {
final int chicken = 0x1;
final int curry = 0x2;
PizzaFactory factory;
//看到这里依赖的并不是具体类,而是接口
public PizzaStore(PizzaFactory factory){
this.factory = factory;
}
Pizza order(int type){
if(type == chicken){
return factory.createChickenPizza();
}else if(type == curry){
return factory.createCurryPizza();
}else{
return null;
}
}
}
新建一个工厂抽象接口:
public interface PizzaFactory {
Pizza createChickenPizza();
Pizza createCurryPizza();
}
创建具体的南京&上海的Pizza工厂:
public class ShanghaiPizzaFactory implements PizzaFactory{
@Override
public Pizza createChickenPizza() {
return new ShanghaiChickenPizza();
}
@Override
public Pizza createCurryPizza() {
return new ShanghaiCurryPizza();
}
}
。。。南京就不列出了
理解:
从Pizza店抠出创建Pizza的代码,对这个代码抽象成一个PizzaFactory接口,然后用到工厂方法写出具体的实现子类,有南京的PizzaFactory和上海的PizzaFactory
抽象工厂定义:
提供一个接口,用于创建相关或者依赖的对象的家族,而不需要明确指定具体类
与工厂方法的区别:
1》工厂方法是通过继承来实现,而抽象工厂是通过组合
2》工厂方法用来创建一个产品,而抽象工厂则是用来创建一个产品家族
抽象工厂缺点:
1》一旦产品家族里新增成员,就必须修改抽象接口了
抽象工厂优点:
1》将客户与具体产品解耦,封装变化利于维护
2》因为客户使用的是一个接口,我们方便给客户替换产品家族
3》而切抽象工厂接口可以面对多个客户,代码复用