设计模式学习——工厂模式

在装饰者模式中我们讲到一条设计原则,即我们应该为对象间的松耦合而努力。

在初始化对象时,除了使用new操作符之外,还有更多制造对象的方法,实例化这个活动不应该总是公开的进行,初始化经常造成“耦合”问题,我们不希望这样,而工厂模式能够将我们从复杂的依赖中解脱出来。


工厂模式

  • 简单工厂模式
  • 工厂方法
  • 抽象工厂模式

简单工厂模式

准确的说,简单工厂其实不是一个设计模式,反而比较像是一种编程习惯

  • 工厂客户:持有工厂的依赖,使用工厂生产出来的产品,不关系产品的具体生产过程
  • 简单工厂:生产产品,即负责产品的实例化
  • 抽象产品:产品类接口
  • 具体产品:具体产品实现类

例子

现在有家披萨店,里面有奶酪披萨(cheese pizza),意大利香肠披萨(pepperoni pizze),素披萨(veggie pizza)这三种披萨,对外提供一个预定披萨的方法(orderPizza),我们来看下非工厂模式下会如何实现:

package factory;

/**
 * 披萨店,提供预定披萨的做法
 */
public class PizzaStore {

    public Pizza orderPizza(String type){
        
        Pizza pizza = null;
        if(type.equals("cheese")){
            pizza = new CheesePizza();
        }else if(type.equals("pepperoni")){
            pizza = new PepperoniPizza();
        }else if(type.equals("veggie")){
            pizza = new VeggiePizza();
        }
        
        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();
        return pizza;
    }
}

如果这家店现在上新了新披萨,或者说不做某种披萨了,那么我们就会对这段代码将作出大量改动,即

我们没有对变化的部分封装

那么接下来我们就使用简单工厂来实现这个功能:

package factory;

/**
 * 简单披萨工厂
 */
public class SimplePizzaFactory {
    public Pizza createPizza(String type){
        Pizza pizza = null;
        if(type.equals("cheese")){
            pizza = new CheesePizza();
        }else if(type.equals("veggie")){
            pizza = new PepperoniPizza();
        }else if(type.equals("epperoni")){
            pizza = new VeggiePizza();
        }
        return pizza;
    }
}
package factory;

/**
 * 披萨店,提供预定披萨的做法
 */
public class PizzaStore {
    private SimplePizzaFactory pizzaFactory = new SimplePizzaFactory();

    public Pizza orderPizza(String type){

        Pizza pizza = pizzaFactory.createPizza(type);
//        if(type.equals("cheese")){
//            pizza = new CheesePizza();
//        }else if(type.equals("pepperoni")){
//            pizza = new PepperoniPizza();
//        }else if(type.equals("veggie")){
//            pizza = new VeggiePizza();
//        }

        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();
        return pizza;
    }
}

我们看到,披萨的实例化功能交给了这个工厂类实现,需要改动的话只需到工厂类中去改动,披萨店不再关系披萨的具体实例化过程,它只知道它拿到的是“一份披萨”,但缺点就是,改动依旧需要到工厂类中去改。

工厂方法

如果现在有另外一家地区的披萨店想加盟,但是因为两个地区之间的烘焙,准备原料方法都有差异,所以做出来的披萨是不一样的,那么针对这种需求,我们又该怎么办呢?工厂方法是一个很好的选择,它定义了一个创建对象的接口,但由子类来决定具体实例化的是哪个。工厂方法把实例化工作交给了子类。

  • 客户:不再赘述
  • 抽象产品:即一类产品族

例子

以上述披萨店加盟为例,地区A为北京,地区B为上海

改写父类披萨店,让其添加抽象方法——创建披萨:

package factory;

/**
 * 披萨店,提供预定披萨的做法
 */
public abstract class PizzaStore {
//    private SimplePizzaFactory pizzaFactory = new SimplePizzaFactory();

    public Pizza orderPizza(String type){
        Pizza pizza = createPizza(type);
//        Pizza pizza = pizzaFactory.createPizza(type);
//        if(type.equals("cheese")){
//            pizza = new CheesePizza();
//        }else if(type.equals("pepperoni")){
//            pizza = new PepperoniPizza();
//        }else if(type.equals("veggie")){
//            pizza = new VeggiePizza();
//        }

        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();
        return pizza;
    }

    public abstract Pizza createPizza(String type);
    //其他方法
}

分别实现上海和北京的披萨店

package factory;

/**
 * 北京的披萨店
 */
public class PekingPizzaStore extends PizzaStore {
    @Override
    public Pizza createPizza(String type) {
        Pizza pizza = null;
        if(type.equals("cheese")){
            pizza = new CheesePizza();
       }else if(type.equals("pepperoni")){
           pizza = new PepperoniPizza();
       }else if(type.equals("veggie")){
           pizza = new VeggiePizza();
        }
        return pizza;
    }
}
package factory;

/**
 * 上海披萨店
 */
public class ShanghaiPizzaStore extends PizzaStore {
    @Override
    public Pizza createPizza(String type) {
        Pizza pizza = null;
        if(type.equals("cheese")){
            pizza = new CheesePizza();
        }
        return pizza;
    }
}

接下去,我们就可以利用上海或者北京的披萨店来实例化我们的披萨了。

抽象工厂

现在我们有了两家分店,但很显然,这两家分店用来做披萨的原料不会一样,因为两个地区人们的口味不一样,现在,我们需要创建原料工厂类满足这个功能,在这里,抽象工厂模式得到了很好的体现。

例子

首先,让我们创建一个原料工厂:

package factory;

/**
 * 原料工厂接口
 */
public interface PizzaIngredientFactory {
    Dough createDough();
    Sauce createSauce();
    Cheese createCheese();
}

上海原料工厂

package factory;

public class SHPizzaIngredientFactory implements PizzaIngredientFactory {
    @Override
    public Dough createDough() {
        return new Dough();
    }

    @Override
    public Sauce createSauce() {
        return new Sauce();
    }

    @Override
    public Cheese createCheese() {
        return new Cheese();
    }
}

改写披萨类(以奶油披萨为例)

package factory;

public class CheesePizza extends Pizza {
    PizzaIngredientFactory ingredientFactory;

    public CheesePizza(PizzaIngredientFactory ingredientFactory) {
        this.ingredientFactory = ingredientFactory;
    }

    @Override
    public void prepare() {
        dough = ingredientFactory.createDough();
        sauce = ingredientFactory.createSauce();
        cheese = ingredientFactory.createCheese();
    }

    @Override
    public void bake() {

    }

    @Override
    public void cut() {

    }

    @Override
    public void box() {

    }
}

实现上海披萨店:

package factory;

/**
 * 上海披萨店
 */
public class ShanghaiPizzaStore extends PizzaStore {
    
    @Override
    public Pizza createPizza(String type) {
        PizzaIngredientFactory pizzaIngredientFactory = new SHPizzaIngredientFactory();
        Pizza pizza = null;
        if(type.equals("cheese")){
            pizza = new CheesePizza(pizzaIngredientFactory);
        }
        return pizza;
    }
}

源码在这里:我的github地址


猜你喜欢

转载自blog.csdn.net/lpckr94/article/details/81172652
今日推荐