工厂设计模式完全解析(利用反射机制+泛型实现可用的工厂设计模式)

下面我们先来写一个传统的工厂类模型,这个工厂类只是一个模型,开发中一般不用,因为这个工厂类模型存在着诸多问题(注释:我的程序的包名可能跟你的不一样,所以在运行下面几个程序的时候把我的包名换乘你自己的)。

package com.demo.testdemo;

//水果接口
interface IFruit{
	public void eat();
}
//苹果类实现了水果接口,并覆写了eat()方法
class Apple implements IFruit{
	public void eat() {
		System.out.println("苹果可以削皮吃");
	}
}
//香蕉类实现了水果接口,覆写eat()方法
class Banana implements IFruit{
	public void eat() {
		System.out.println("香蕉需要剥皮吃");
	}
}
//写一个工厂类,“输入”进工厂的东西就被工厂加工之后出来。
class Factory{
	private Factory() {}//工厂类的构造方法为私有
	public static IFruit getInstnce(String classname) {
		if("apple".equals(classname)) {
			return new Apple();
		}else if("banana".equals(classname)) {
			return new Banana();
		}
		return null;
	}
}
public class TestDemo{
	public static void main(String args[]) {
		Apple apple=(Apple)Factory.getInstnce("apple");
		apple.eat();
		Banana banana=(Banana)Factory.getInstnce("banana");
		banana.eat();
	}
}

以上程序的输出:

苹果可以削皮吃
香蕉需要剥皮吃

完美的实现了输出。但是,虽然完美的实现了输出,这个程序却没有一点实用价值,用来教学演示还可以。为什么没有价值呢?

因为:我们现在有两个类实现了接口,于是要想输出eat()方法里面的内容,我们必须通过Factory类来new出该类,意思就是说假如我们现在有千千万万个已经实现了IFruit接口的水果类,那么我们就必须在Factory类里面new出千千万万个水果类。在一个项目之中实现一个接口的子类是很多的,,而Factory类的功能也只有一件,那就是通过判断,然后new出一个实例。所以传统工厂类的最大弊端也就是关键字new,这个弊端会导致我们的程序开发过程中Factory类越写越大。既然是这样,那我们为什么不使用java反射来解决问题呢?

下面是使用java反射类解决问题。要想理解下面的代码需要对java反射的基础知识有一点了解。

首先java反射需要使用到Class类,这个类里面有许多关于反射的方法,对于Class类的实例化有三种方法,下面程序中使用的

Class cls=Class.forName("包名+类名");//这是实例化Class类的方法之一
至于newInstance()这个方法,是Class类里面的一个方法,
主要作用是实例化想要反射的类,返回的是Object对象。
package com.demo.testdemo;

//水果接口
interface IFruit{
	public void eat();
}
//苹果类实现了水果接口,并覆写了eat()方法
class Apple implements IFruit{
	public void eat() {
		System.out.println("苹果可以削皮吃");
	}
}
//香蕉类实现了水果接口,覆写eat()方法
class Banana implements IFruit{
	public void eat() {
		System.out.println("香蕉需要剥皮吃");
	}
}
//写一个工厂类,“输入”进工厂的东西就被工厂加工之后出来。
class Factory{
	private Factory() {}//工厂类的构造方法为私有
	public static IFruit getInstnce(String classname) {
		IFruit fruit=null;
		try {
			fruit=(IFruit)Class.forName(classname).newInstance();
		}catch(Exception e) {
			e.printStackTrace();
		}
		return fruit;
	}
}
public class TestDemo{
	public static void main(String args[]) {
		Apple apple=(Apple)Factory.getInstnce("com.demo.testdemo.Apple");
		apple.eat();
		Banana banana=(Banana)Factory.getInstnce("com.demo.testdemo.Banana");
		banana.eat();
	}
}

上面程序中主方法中的“com.demo.testdemo”这个包名要换成你自己的包名,这个包名是我的工程中的包名。程序输出的结构是:

苹果可以削皮吃
香蕉需要剥皮吃

也是一个完美的输出,虽然程序已经很完美了,但是我还是要告诉你,这个完美的程序依然在工程中用不上。那这次又是为什么用不上呢?因为上面的程序虽然解决了重复造对象的问题,但是我们可以发现这个程序只能够造关于水果类的对象。假如现在我有千千万万个接口,那么我们就要写千千万万次Factory类,而且所有Factory类的作用是一样的,到时候你肯定会觉得很烦,那么有什么办法来解决吗?

下面我们就使用泛型来解决上面出现的问题。

package com.demo.testdemo;

//水果接口
interface IFruit{
	public void eat();
}
//苹果类实现了水果接口,并覆写了eat()方法
class Apple implements IFruit{
	public void eat() {
		System.out.println("苹果可以削皮吃");
	}
}
//香蕉类实现了水果接口,覆写eat()方法
class Banana implements IFruit{
	public void eat() {
		System.out.println("香蕉需要剥皮吃");
	}
}

//增加一个Person接口
interface Person{
	public void info();
}
//Student 类实现Person接口
class Student implements Person{
	public void info() {
		System.out.println("这是一个学生类");
	}
}


//写一个工厂类,“输入”进工厂的东西就被工厂加工之后出来。
class Factory{
	private Factory() {}//工厂类的构造方法为私有
	public static T getInstnce(String classname) {
		T obj=null;
		try {
			obj=(T)Class.forName(classname).newInstance();
		}catch(Exception e) {
			e.printStackTrace();
		}
		return obj;
	}
}
public class TestDemo{
	public static void main(String args[]) {
		Apple apple=(Apple)Factory.getInstnce("com.demo.testdemo.Apple");
		apple.eat();
		Banana banana=(Banana)Factory.getInstnce("com.demo.testdemo.Banana");
		banana.eat();
		
		Student stu=Factory.getInstnce("com.demo.testdemo.Student");
		stu.info();
	}
}

上面程序的输出:

苹果可以削皮吃
香蕉需要剥皮吃
这是一个学生类

于是问题完美解决,我们定义了一个Person接口,而且实现了这个接口,但是只有一个Factory类,一样完美的输出了。是不是很开心。

本次内容就讲到这里。如果有时间的话我再把java反射机制的知识给大家梳理一遍。

你可能感兴趣的:(java)