Java 反射与工厂设计模式

文章目录

    • 案例: 编写一个传统的工厂类
    • 改进: 通过使用反射来完成处理对象的实例化
    • 改进: 使用泛型解决优化
    • 总结:

工厂设计曾经给过一个原则: 如果是你自己所编写的接口, 要想取得本接口的实例化对象, 最好使用工厂类来设计, 但是也需要知道传统工厂设计所带来的问题.

案例: 编写一个传统的工厂类

package com.cwq.beyond;

interface IFruit{
     
	public void eat();
}

class Apple implements IFruit{
     
	
	@Override
	public void eat() {
     
		System.out.println("[Apple]吃苹果.");
	}
}

class Factory{
     
	private Factory() {
     }
	public static IFruit getInstance(String className) {
     
		if ("apple".equals(className)) {
     
			return new Apple();
		}
		return null;
	}
}

public class TestDemo04 {
     
	public static void main(String[] args) throws Exception {
     
		IFruit fruit = Factory.getInstance("apple");
		fruit.eat();
	}
}

但是非常遗憾的是: 该工厂设计类在开发中根本就不可能使用, 因为在传统的工厂设计中, 当增加一个类的时候需要修改工厂类.
所以传统工厂类的最大弊端: 关键字 new

改进: 通过使用反射来完成处理对象的实例化

因为 Class 类可以使用 newInstance() 实例化对象, 同时 Class.forName() 能够接收 String 这个类名称.

package com.cwq.beyond;

interface IFruit {
     
	public void eat();
}

class Apple implements IFruit {
     

	@Override
	public void eat() {
     
		System.out.println("[Apple]吃苹果.");
	}
}

class Cherry implements IFruit {
     

	@Override
	public void eat() {
     
		System.out.println("[Cherry]吃樱桃.");
	}
}

class Orange implements IFruit {
     

	@Override
	public void eat() {
     
		System.out.println("[Orange]吃橘子.");
	}
}

class Factory {
     
	private Factory() {
     
	}

	public static IFruit getInstance(String className) {
     
		IFruit fruit = null;
		try {
     
			fruit = (IFruit) Class.forName(className).newInstance();
		} catch (Exception e) {
     
			e.printStackTrace();
		}
		return fruit;
	}
}

public class TestDemo04 {
     
	public static void main(String[] args) throws Exception {
     
		IFruit fruit = Factory.getInstance("com.cwq.beyond.Apple");
		IFruit fruit2 = Factory.getInstance("com.cwq.beyond.Orange");
		IFruit fruit3 = Factory.getInstance("com.cwq.beyond.Cherry");
		fruit.eat();
		fruit2.eat();
		fruit3.eat();
	}
}

所以现在可以发现, 通过反射类改进的工厂设计模式, 其最大的特征在于可以方便动态进行子类的扩充操作, 而关键字new 会造成耦合问题.
但是以上的程序依然存在缺陷 : 如果所 ,现在有 10W 个接口, 那么按照此类模式就意味着需要有 10W 个工厂, 而10W 个工厂完成的都是相同的功能, 这样就很浪费了, 所以使用泛型来解决此问题.

改进: 使用泛型解决优化

package com.cwq.beyond;

interface IMessage{
     
	public void print();
}

class MessageImpl implements IMessage{
     
	@Override
	public void print() {
     
		System.out.println("com.cwq.beyond");
	}
}


interface IFruit {
     
	public void eat();
}

class Apple implements IFruit {
     

	@Override
	public void eat() {
     
		System.out.println("[Apple]吃苹果.");
	}
}

class Cherry implements IFruit {
     

	@Override
	public void eat() {
     
		System.out.println("[Cherry]吃樱桃.");
	}
}

class Orange implements IFruit {
     

	@Override
	public void eat() {
     
		System.out.println("[Orange]吃橘子.");
	}
}

class Factory {
     
	private Factory() {
     
	}

	public static <T> T getInstance(String className) {
     
		T t = null;
		try {
     
			t = (T) Class.forName(className).newInstance();
		} catch (Exception e) {
     
			e.printStackTrace();
		}
		return t;
	}
}

public class TestDemo04 {
     
	public static void main(String[] args) throws Exception {
     
		IFruit fruit = Factory.getInstance("com.cwq.beyond.Apple");
		IFruit fruit2 = Factory.getInstance("com.cwq.beyond.Orange");
		IFruit fruit3 = Factory.getInstance("com.cwq.beyond.Cherry");
		fruit.eat();
		fruit2.eat();
		fruit3.eat();
		IMessage msg = Factory.getInstance("com.cwq.beyond.MessageImpl");
		msg.print();
	}
}

从实际的开发来讲, 工厂类上使用泛型之后, 就可以为更多的类和接口进行服务了, 这应该是之后实际开发中要使用的工厂方式.

总结:

在实际开发之中, 如果可以掌握这种泛型和反射的组合操作原则, 那么对于整体的代码你就可以编写出高可用的程序了.

你可能感兴趣的:(Java算法及JDK源码探究,日常小知识随笔,我的百宝箱,java,设计模式)