工厂模式(Factory Design Pattern):也是创建型中常用设计模式;又可细分为三种类型:简单工厂,工厂方法,抽象工厂;工厂顾名思义就是生产产品,在这里是指创建对象;工
下面通过动物饲养的例子,实现简单工厂模式;
1,创建一个动物接口:
public interface Animal {//动物抽象
void eat();//动物的行为
}
2,具体的动物类(具体对象类)
public class Dog implements Animal {
@Override
public void eat() {
System.out.println("狗吃骨头!");
}
}
public class Cat implements Animal {
@Override
public void eat() {
System.out.println("猫吃鱼!");
}
}
public class Sheep implements Animal {
@Override
public void eat() {
System.out.println("羊吃草!");
}
}
3,创一个饲养厂(工厂),专门饲养(创建对象)各种动物
public class AnimalFactory {
public static Animal createAnimal(String name) {
if ("dog".equalsIgnoreCase(name)) {
return new Dog();
} else if ("cat".equalsIgnoreCase(name)) {
return new Cat();
}else if ("sheep".equalsIgnoreCase(name)) {
return new Sheep();
}
return null;
}
}
工厂类中创建对象的方法一般都是 create 开头,比如代码中的 createAnimal(),但有的也命名为 getInstance()、reateInstance()、newInstance(),这个我们根据具体的场景和习惯来命名就好。一般方法都是静态的,所以有些还成为静态工厂;
以上就是简单工厂模式;
使用:
public class Demo {
public static void main(String[] args) {
Animal dog = AnimalFactory.createAnimal("Dog");
dog.eat();
Animal cat = AnimalFactory.createAnimal("cat");
cat.eat();
Animal sheep = AnimalFactory.createAnimal("Sheep");
sheep.eat();
}
}
总结:简单工厂存在一个问题就是,如果再增加一种动物,那就要增加一个实体类继承Animal接口,然后修改工厂类,这样不太符合开闭原则:对扩展开放,对修改关闭;实际如果不平凡的增加动物(实体类),也没有太多动物,这样的修改也是可以接受的;
如果要解决简单工厂缺点,工厂方法就应运而生了,也是简单工厂的升级;具体可以通过多态对工厂类实现可扩展;重构工厂类如下:
public interface IAnimalFactory {
Animal createAnimal();
}
public class DogAnimalFactory implements IAnimalFactory {
@Override
public Animal createAnimal() {
return new Dog();
}
}
public class CatAnimalFactory implements IAnimalFactory {
@Override
public Animal createAnimal() {
return new Cat();
}
}
public class SheepAnimalFactory implements IAnimalFactory {
@Override
public Animal createAnimal() {
return new Sheep();
}
}
以上就是典型的工厂方法模式实现;把工厂类又抽象了一层;具体动物类创建,就到了工厂接口的具体实现类中;
使用:
public class Demo {
public static void main(String[] args) {
IAnimalFactory dagFactory = createAnimal("dog");
Animal dog = dagFactory.createAnimal();
IAnimalFactory dagFactory = createAnimal("cat");
Animal dog = dagFactory.createAnimal();
}
public static IAnimalFactory createAnimal(String name) {
if ("dog".equalsIgnoreCase(name)) {
return new DogAnimalFactory();
} else if ("cat".equalsIgnoreCase(name)) {
return new CatAnimalFactory();
}else if ("sheep".equalsIgnoreCase(name)) {
return new SheepAnimalFactory();
}
return null;
}
}
在以上的使用过程中还会发现,createAnimal()方法去掉过多的if-else,还可以创建一个简单工厂方式,去掉过多if-else,也就是工厂的工厂,用来创建工厂类对象;具体实现如下:单例模式实现简单工厂;
class AnimalFactoryMap {
private static final Map cachedFactories = new HashMap<>();
static {
cachedFactories.put("dog", new DogAnimalFactory());
cachedFactories.put("cat", new CatAnimalFactory());
cachedFactories.put("sheep", new SheepAnimalFactory());
}
public static IAnimalFactory getParserFactory(String type) {
if (type == null || type.isEmpty()) {
return null;
}
IAnimalFactory animalFactory = cachedFactories.get(type.toLowerCase());
return animalFactory;
}
}
简单工厂和工厂方法什么时候用?
当对象的创建逻辑比较复杂,不只是简单的 new 一下就可以,而是要组合其他类对象,做各种初始化操作的时候,我们推荐使用工厂方法模式,将复杂的创建逻辑拆分到多个工厂类中,让每个工厂类都不至于过于复杂。而使用简单工厂模式,将所有的创建逻辑都放到一个工厂类中,会导致这个工厂类变得很复杂。
这个不好用以上案例进行解释,以一个工厂,即生产手机有生产电脑为例;如下
手机接口类
public interface Phone {
void call();
}
手机实体类
public class HuaweiPhone implements Phone {
@Override
public void call() {
System.out.println("用华为手机打电话!");
}
}
public class XiaoMiPhone implements Phone {
@Override
public void call() {
System.out.println("用小米手机打电话!");
}
}
电脑接口类
public interface Computer {
void work();
}
电脑实体类
public class MacComputer implements Computer {
@Override
public void work() {
System.out.println("用苹果电脑工作");
}
}
public class DellComputer implements Computer {
@Override
public void work() {
System.out.println("用戴尔电脑工作");
}
}
抽象工厂类
为Computer和Phone创建接口来获取工厂;
public interface AbstractFactory {
Computer createComputer(String name);//根据name获取不同品牌的电脑对象;
Phone createPhone(String name);//根据name获取不同品牌的手机对象;
}
使用:以富士康为例
public class FuShiKangFactory implements AbstractFactory {
@Override
public Computer createComputer(String name) {
if ("mac".equalsIgnoreCase(name)) {
return new MacComputer();
} else if ("dell".equalsIgnoreCase(name)) {
return new DellComputer();
}
return null;
}
@Override
public Phone createPhone(String name) {
if ("huawei".equalsIgnoreCase(name)) {
return new HuaweiPhone();
} else if ("xiaomi".equalsIgnoreCase(name)) {
return new XiaoMiPhone();
}
return null;
}
}
总结:抽象工厂的另一种写法就是把Computer和Phone的实现类都是同一个品牌;这样一个工厂就只生产一个品牌的Phone和Computer
改进:
手机接口类
public interface Phone {
void call();
}
手机实体类
public class HuaweiPhone implements Phone {
@Override
public void call() {
System.out.println("用华为手机打电话!");
}
}
public class XiaoMiPhone implements Phone {
@Override
public void call() {
System.out.println("用小米手机打电话!");
}
}
电脑接口类
public interface Computer {
void work();
}
电脑实体类
public class HuaWeiComputer implements Computer {
@Override
public void work() {
System.out.println("用华为电脑工作");
}
}
public class XiaoMiComputer implements Computer {
@Override
public void work() {
System.out.println("用小米电脑工作");
}
}
抽象工厂类
为Computer和Phone创建接口来获取工厂;
public interface AbstractFactory {
Computer createComputer();
Phone createPhone();
}
使用:
小米工厂
public class XiaoMiFactory implements AbstractFactory2 {
@Override
public Computer createComputer() {
return new XiaoMiComputer();
}
@Override
public Phone createPhone() {
return new XiaoMiPhone();
}
}
华为工厂
public class HuaWeiFactory implements AbstractFactory2 {
@Override
public Computer createComputer() {
return new HuaweiComputer();
}
@Override
public Phone createPhone() {
return new HuaweiPhone();
}
}
总结:工厂模式可以应用到自定义依赖注入框架种,通过读取配置文件,经过工厂模式创建出对象;工厂模式是用来创建不同但是相关类型的对象(继承同一父类或者接口的一组子类),由给定的参数来决定创建哪种类型的对象。