《4》工厂模式

概述:


工厂模式可分为3小类:


简单工厂、工厂方法、抽象工厂







  1. 简单工厂


直接上例子:

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》而且修改的时候,也只要修改这个简单工厂类即可










  1. 工厂方法

    上类图(这次是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哪个,是在代码中写死的(非动态)








  1. 抽象工厂

    设计原则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》而切抽象工厂接口可以面对多个客户,代码复用


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章