概念
工厂模式属于创建型的设计模式,工厂模式不会暴露创建逻辑,解决了接口选择的问题。具体是由子类决定要实例化的类是哪一个。工厂方法吧实例化推迟到子类。
简单工厂
解释工厂方法模式之前先说一下简单工厂,这应该并不算是一种设计模式,而是一种习惯。
我们以动物为例
首先我们先有一个动物的接口,这个接口提供了吃和叫两个方法,这两个方法是动物共有的特性
public interface Animal {
//吃
void eat();
//叫
void call();
}
我们再定义一些具体的动物
波斯猫
public class BoSiCat implements Animal{
@Override
public void eat() {
System.out.println("波斯猫:吃东西");
}
@Override
public void call() {
System.out.println("波斯猫:叫");
}
}
布偶猫
public class BuOuCat implements Animal{
@Override
public void eat() {
System.out.println("布偶猫:吃东西");
}
@Override
public void call() {
System.out.println("布偶猫:叫");
}
}
二哈
public class TwoHaDog implements Animal {
@Override
public void eat() {
System.out.println("二哈:吃东西");
}
@Override
public void call() {
System.out.println("二哈:叫");
}
}
萨摩耶
public class SaMoYeDog implements Animal{
@Override
public void eat() {
System.out.println("萨摩耶:吃东西");
}
@Override
public void call() {
System.out.println("萨摩耶:叫");
}
}
提供一个宠物商店类
public class PetStore {
Animal createAnimal(String type)
{
Animal animal = null;
if ("twoHaDog".equals(type)) {
animal = new TwoHaDog();
}
if ("saMoYeDog".equals(type)) {
animal = new SaMoYeDog();
}
if("boSi".equals(type))
{
animal = new BoSiCat();
}
if("buOu".equals(type))
{
animal = new BuOuCat();
}
return animal;
}
public void animalInfo(String type)
{
Animal animal = createAnimal(type);
animal.eat();
animal.call();
}
}
好的,这下客户来了
public static void main(String[] args) {
System.out.println("客户想看:波斯猫");
new PetStore().animalInfo("boSi");
System.out.println("客户想看:哈士奇");
new PetStore().animalInfo("twoHaDog");
}
输出:
客户想看:波斯猫
波斯猫:吃东西
波斯猫:叫
客户想看:哈士奇
二哈:吃东西
二哈:叫
这就是一个简单工厂。但是突然有一天老板突然想在其他地方开分店,且分店因为经营模式的好坏导致宠物们的食物也分好坏,比如说重庆的宠物店经营不好狗这一类吃的一般的狗粮,广州的宠物店经营非常好狗这一类吃的非常好的狗粮,但是简单工厂每次新增分店就会修改原有的代码。这违反了设计原则中 开闭原则,所以就引出了工厂方法模式。
工厂方法模式
我们将原来的代码进行改造,并且新增重庆和广州的分店
将创建方法抽象出来,分别由重庆分店和广州分店分别继承和实现
public abstract class PetStore {
abstract Animal createAnimal(String type);
public void animalInfo(String type)
{
Animal animal = createAnimal(type);
animal.eat();
animal.call();
}
}
重庆分店
public class CqFactory extends PetStore {
@Override
public Animal createAnimal(String type) {
Animal animal = null;
if (type.equals("twoHaDog")) {
animal = new CqTwoHaDog();
}
if (type.equals("saMoYeDog")) {
animal = new CqSaMoYeDog();
}
if("boSi".equals(type))
{
animal = new CqBoSiCat();
}
if("buOu".equals(type))
{
animal = new CqBuOuCat();
}
return animal;
}
}
广州分店
public class GzFactory extends PetStore {
@Override
public Animal createAnimal(String type) {
Animal animal = null;
if (type.equals("twoHaDog")) {
animal = new GzTwoHaDog();
}
if (type.equals("saMoYeDog")) {
animal = new GzSaMoYeDog();
}
if("boSi".equals(type))
{
animal = new GzBoSiCat();
}
if("buOu".equals(type))
{
animal = new GzBuOuCat();
}
return animal;
}
}
各分店的宠物实体类的代码就不拿出来了,大概是下面这个结构
广州和重庆的分店分别来了一个看宠物的
public static void main(String[] args) {
System.out.println("客户在广州,他想看:二哈");
PetStore gzFactory = new GzFactory();
gzFactory.animalInfo("twoHaDog");
System.out.println("客户在重庆,他想看:波斯猫");
PetStore cqFactory = new CqFactory();
cqFactory.animalInfo("boSi");
}
输出:
客户在广州,他想看:二哈
二哈:吃特别好的狗粮
二哈:叫
客户在重庆,他想看:波斯猫
波斯猫:吃一般的猫粮
波斯猫:叫
从这里可以看到,我们将创建分店的动作交给了子类进行,这样每次新增分店的时候我们就不需要去修改原来的代码,而是增加新的分店工厂,并且增加对于的宠物。