概况
工厂模式是创建型模式的一种,主要遵循依赖倒转原则,强调的是依赖于抽象类或者实现接口的方式去编码,在创建对象的时候,提倡将实例化的操作封装在一个工厂的方法中,而不是直接使用new关键字。工厂模式有三种,分别是简单工厂模式,工厂方法模式和抽象工厂模式。这种模式的意义在于他时刻希望我们面向接口编程以达到解耦的目的,有利于后期代码的维护和扩展。
简单工厂模式
简单工厂模式的核心思想是将实例化的逻辑封装在一个类里,封装在一个类里的好处就是便于集中管理。举个例子,假设有两个披萨店A1和A2,他们可以做的披萨种类一模一样,只是生产流程略有不同,那么在两个类里创建披萨对象的代码就会一模一样。如果有一天有一种新的披萨类型引入时,我们就得分别改两个地方的代码,但如果使用简单工厂模式我们只需要修改一处即可。
/**
* 简单工厂模式
*/
public class SimpleFactory {
public Pizza creatPizza(String type){
Pizza pizza = null;
if(type.equals("A")){
pizza = new PizzaA();
}else if(type.equals("b")){
pizza = new PizzaB();
}
return pizza;
}
}
class PizzaStoreC{
SimpleFactory simpleFactory;
public void setSimpleFactory(SimpleFactory simpleFactory) {
this.simpleFactory = simpleFactory;
}
public Pizza creatPizza(String type){
Pizza pizza = simpleFactory.creatPizza(type);
return pizza;
}
public void cutA(){}
public void boxA(){};
}
class PizzaStoreD{
SimpleFactory simpleFactory;
public void setSimpleFactory(SimpleFactory simpleFactory) {
this.simpleFactory = simpleFactory;
}
public Pizza creatPizza(String type){
Pizza pizza = simpleFactory.creatPizza(type);
return pizza;
}
public void cutB(){}
public void boxB(){}
}
//下面的这种写法有一个问题,即当新加一种类型时,PizzaStoreA和PizzaStoreB都需要修改
class PizzaStoreA{
public Pizza creatPizza(String type){
Pizza pizza = null;
if(type.equals("A")){
pizza = new PizzaA();
}else if(type.equals("b")){
pizza = new PizzaB();
}
return pizza;
}
public void cutA(){}
public void boxA(){};
}
class PizzaStoreB{
public Pizza creatPizza(String type){
Pizza pizza = null;
if(type.equals("A")){
pizza = new PizzaA();
}else if(type.equals("b")){
pizza = new PizzaB();
}
return pizza;
}
public void cutB(){}
public void boxB(){}
}
class Pizza{
String name;
}
class PizzaA extends Pizza{
}
class PizzaB extends Pizza{
}
工厂方法模式
工厂方法模式的核心思想是将实例化对象的操作交给子类,父类只定义一个创建对象的抽象方法,具体实现交给子类去完成,这样就能起到不同的子类可以根据自身的需要去创建对象的作用,因为在实际生活中,不同的子类往往有不同的需求。举个例子,有两个披萨店A1和A2,A1店只能做P1类型的披萨,A2店只能做P2类型的披萨,除此之外A1和A2的其他属性都一样,那么这个时候我们就可以写一个抽象类A,将A1和A2的相同的属性封装在A中,将创建披萨的方法设计成一个抽象类,然后让A1和A2去继承A重写创建披萨的方法,是不是很好的就解决了需求,此时的抽象方法就如同上面提到的简单工厂,不同的是前者是类而后者是一个抽象方法。
/**
* 工厂方法模式
*/
public abstract class FactoryMethod {
public abstract Pizza creat(String type);
}
class PizzaStoreForC extends FactoryMethod {
@Override
public Pizza creat(String type) {
Pizza pizza = null;
if (type.equals("A")) {
pizza = new PizzaForA1();
} else if (type.equals("b")) {
pizza = new PizzaForA2();
}
return pizza;
}
}
class PizzaStoreForD extends FactoryMethod {
@Override
public Pizza creat(String type) {
Pizza pizza = null;
if (type.equals("A")) {
pizza = new PizzaForB1();
} else if (type.equals("b")) {
pizza = new PizzaForB2();
}
return pizza;
}
}
//下面的这种写法,我们发现PizzaStoreForA和PizzaStoreForB除了create方法不一样其他的都一样,
// 这个时候我们可以考虑用工厂方法设计模式来优化
//使用工厂方法模式来编码单纯从代码看仿佛并没有带来可见的好处,但是却满足了依赖抽象的方式编码
class PizzaStoreForA {
public Pizza creat(String type) {
Pizza pizza = null;
if (type.equals("A")) {
pizza = new PizzaForA1();
} else if (type.equals("b")) {
pizza = new PizzaForA2();
}
return pizza;
}
}
class PizzaStoreForB {
public Pizza creat(String type) {
Pizza pizza = null;
if (type.equals("A")) {
pizza = new PizzaForB1();
} else if (type.equals("b")) {
pizza = new PizzaForB2();
}
return pizza;
}
}
class PizzaForA1 extends Pizza {
}
class PizzaForA2 extends Pizza {
}
class PizzaForB1 extends Pizza {
}
class PizzaForB2 extends Pizza {
}
抽象工厂模式
从设计层面来看,抽象工厂模式可以理解成简单工厂模式的升级版,因为它对工厂进行了进一步的抽象,即将工厂抽象成一个AbstractFactory和具体实现AabstractFactory的子类工厂对象,那么这样做有什么好处呢?从简单工厂模式我们可以知道一个工厂可以管多个同类型的披萨店,那么如果有一天有第三个披萨店,且第三个披萨店能做的披萨种类和前两个披萨店完全不同,那么这时就意味着我们必须有一个不同的披萨工厂,而用抽象工厂模式完全可以实现。但是可不可以换另一种方式呢,比如我用简单工厂的模式再新建一个工厂类不一样可以解决问题吗?答案当然是可以的,但是我们一开始就有提到,设计模式是站在软件的角度考虑问题的,并不是局限于功能的实现,抽象工厂对工厂进行了进一步抽象,那么他带给我们的是我们在代码中相当于对工厂进行了统一管理,我们应该根据实际需要去选择合适的设计模式。
/**
* 抽象工厂设计模式
*/
public interface AbsFactory {
Pizza creatPizza(String type);
}
class AFactory implements AbsFactory {
@Override
public Pizza creatPizza(String type) {
Pizza pizza = null;
if (type.equals("A")) {
pizza = new PizzaForA1();
} else if (type.equals("b")) {
pizza = new PizzaForA2();
}
return pizza;
}
//其他方法
}
class BFactory implements AbsFactory {
@Override
public Pizza creatPizza(String type) {
Pizza pizza = null;
if (type.equals("A")) {
pizza = new PizzaForB1();
} else if (type.equals("b")) {
pizza = new PizzaForB2();
}
return pizza;
}
//其他方法
}
class PizzaStore{
public Pizza creat(AbsFactory absFactory,String type){
Pizza pizza = absFactory.creatPizza(type);
return pizza;
}
}