肝一肝设计模式【二】-- 工厂模式

系列文章目录

肝一肝设计模式【一】-- 单例模式 传送门
肝一肝设计模式【二】-- 工厂模式 传送门
肝一肝设计模式【三】-- 原型模式 传送门
肝一肝设计模式【四】-- 建造者模式 传送门
肝一肝设计模式【五】-- 适配器模式 传送门
肝一肝设计模式【六】-- 装饰器模式 传送门
肝一肝设计模式【七】-- 代理模式 传送门
肝一肝设计模式【八】-- 外观模式 传送门
肝一肝设计模式【九】-- 享元模式 传送门


文章目录

  • 系列文章目录
  • 前言
  • 一、简单工厂模式
  • 二、工厂方法模式
  • 三、抽象工厂模式
  • 写在最后


前言

在实际开发过程中,构建对象往往使用new的方式来构建,但随着开发时间的拉长,构建对象的逻辑慢慢会在很多类里使用,那就势必会产生大量的重复代码,那就意味着难以维护,所以我们想把创建对象的代码和业务逻辑分离,并通过一个统一的接口创建对象,然后把创建对象的逻辑封装起来,而这些就是工厂模式所解决的问题


一、简单工厂模式

我们拿动物世界举个栗子(最近陪女鹅看动画片看太多,脑子第一时间想到的只有动物o(* ̄3 ̄)o )
肝一肝设计模式【二】-- 工厂模式_第1张图片
我们先定义一个Animal接口

public interface Animal {
    
    public void eat();
}

然后再创建两个实现类兔子和老虎

public class Rabbit implements Animal {

    @Override
    public void eat() {
        System.out.println("我是兔子,我吃胡萝卜");
    }
}
public class Tiger implements Animal {

    @Override
    public void eat() {
        System.out.println("我是老虎,我吃肉");
    }
}

再创建一个AnimalFactory工厂类,有两种方式实现:

  1. 使用逻辑判断方式
public class AnimalFactory {

    public Animal create(String name) {
        if("rabbit".equals(name)) {
            return new Rabbit();
        } else if("tiger".equals(name)) {
            return new Tiger();
        } else {
            System.out.println("啥也不是");
            return null;
        }
    }
}

然后我们测试一下:

public class SimpleFactoryTest {
    public static void main(String[] args) {
        AnimalFactory factory = new AnimalFactory();
        factory.create("rabbit").eat();
    }
}

也可将AnimalFactory工厂类的create()方法改为静态方法,这样调用就更方便一点。

  1. 使用反射方式
public class AnimalFactory {

    public Animal create(Class<? extends Animal> c){
	    try {
	        if (null != c) {
	            return c.newInstance();
	        }
	    }catch (Exception e){
	        e.printStackTrace();
	    }
	    return null;
	}
}

我们测试一下:

public class SimpleFactoryTest {
    public static void main(String[] args) {
        AnimalFactory factory = new AnimalFactory();
        Animal animal = factory.create(Tiger.class);
	    animal.eat();
	}
}

简单工厂模式实质:是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。

二、工厂方法模式

在简单的工厂模式里,我们创建了一个类似工具的类来创建相应的具体类对象,但正因为其太过简单,不符合开闭原则。
工厂方法模式就是把简单工厂中具体的工厂类,划分成两层:抽象工厂层 + 具体的工厂子类层。

肝一肝设计模式【二】-- 工厂模式_第2张图片
我们上面的工厂类进行拆分

  • AnimalFactory(抽象工厂)
public abstract class AnimalFactory {
    public abstract Animal create();
}
  • RabbitFactory(具体的工厂子类)‘
public class RabbitFactory extends AnimalFactory {
    @Override
    public Animal create() {
        return new Rabbit();
    }
}
  • TigerFactory(具体的工厂子类)
public class TigerFactory extends AnimalFactory {
    @Override
    public Animal create() {
        return new Tiger();
    }
}

测试一下

public class FactoryMethodTest {
    public static void main(String[] args) {
        AnimalFactory factory = new RabbitFactory();
	    Rabbit rabbit = factory.create();
	    rabbit.eat();
	}
}

工厂方法模式实质:不仅仅产品要抽象, 工厂也需要抽象。这样的好处就是更拥抱变化,比如现在需要创建一个Cat对象,就不需要像简单工厂模式去修改create()方法,只需新增一个Cat工厂类即可,遵循了开闭原则。

三、抽象工厂模式

工厂方法模式中,具体工厂A和B,两者除了都是抽象工厂的子类,没有任何其他的交集,是完全独立的两个工厂。

那抽象工厂模式中,具体工厂之间就能产生交际。

抽象工厂模式是这么定义的,提供一个创建一系列相关或者相互依赖对象的接口,而无需指定它们具体的类。可以理解为将同一类的产品子类归为一类,让他们继承同一个抽象子类,把他们当做一个组。

比如我们新增一个Cat类,我们可以把猫和兔子分类成宠物类型,也可以把猫和老虎分类成猫科动物类型。

所以代码修改一下:

public class AbstractFactoryClient {
    public static void main(String[] args) {
        AnimalFactory factory = new PetFactory();
		factory.createPet().sayA();
		factory.createMaoke().sayB();
		
		factory = new MaokeFactory();
		factory.createPet().sayA();
		factory.createMaoke().sayB();
	}
	// 抽象工厂类
    public interface AnimalFactory {
        Pet createPet();
        Maoke createMaoke();
    }
    
    // 宠物分类抽象
    public interface Pet {
        void sayA();
    }
    
    // 猫科分类抽象
    public interface Maoke {
        void sayB();
    }
    
    // 宠物分类的兔子
    static class RabbitWithPet implements Pet {
    	@Override
        public void sayA() {
            System.out.println("我是宠物兔");
        }
    }

    // 宠物分类的猫
    static class CatWithPet implements Pet {
    	@Override
        public void sayA() {
            System.out.println("我是宠物猫");
        }
    }
    
    // 猫科分类的猫
    static class CatWithMaoke implements Maoke {
    	@Override
        public void sayB() {
            System.out.println("我能上树,所以我是猫科动物的老大");
        }
    }
    
    // 猫科分类的老虎
    static class TigerWithMaoke implements Maoke {
    	@Override
        public void sayB() {
            System.out.println("老大没教我怎么上树");
        }
    }
    
    // 具体工厂类(宠物)
    static class PetFactory implements AnimalFactory{
    	
    	@Override
        public Pet createPet() {
            return new RabbitWithPet();
        }

		@Override
        public Maoke createMaoke() {
            return new CatWithMaoke();
        }
    }

    // 具体工厂类(猫科)
    static class MaokeFactory implements AnimalFactory{
        
        @Override
        public Pet createPet() {
            return new CatWithPet();
        }

        @Override
        public Maoke createMaoke() {
            return new TigerWithMaoke();
        }
    }
}

在抽象工厂模式中,可以不需要知道产品是什么样的,只需要知道是用哪个工厂类就行了。也可以根据子类的共同特性,将它们设计在一起,组成一个相同类型组,就可以很方便的直接调用。但是相对的,产品族比较难以扩展,增加一个产品,就需要增加相应的接口和实现类。


写在最后

工厂模式关心的是最终创建的对象,而不关心创建的过程,这样做的优点是为创建对象提供统一的接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的,在此同时还能给系统带来更大的可扩展性和尽量少的修改量。

你可能感兴趣的:(#,肝一肝设计模式,设计模式)