工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
1. 为什么要有工厂模式?
"Talk is cheap,show me the code". 想要找到这个问题的答案,我们先来看看下面这个项目。
1.1 一个实体类
public class User{ public String username; public String password;
}
为了更方便讲述,我尽量让代码精简,方便我们深入了解想关注的点。
实体类很简单,User对象,两个成员变量,username 用户名称,password 用户密码
1.2 定义了一个IUser接口
也很简单,只有一个insert方法
import com.xingyun.model.User; public interface IUser { void insert(User user); }
1.3 一个实现类IUserMySQLImpl.java
import com.xingyun.model.User;
import com.xingyun.myinterface.IUser;
public class IUserMySQLImpl implements IUser{
@Override
public void insert(User user) {
// TODO Auto-generated method stub
System.out.println("insert to MySQL"+user.toString());
}
}
这个实现类实现了IUser接口,所以需要实现IUser接口定义的insert(User user)方法.
1.4 最后我们可能需要再多个地方调用
Test1.java
import com.xingyun.model.User; import com.xingyun.myinterface.IUser; import com.xingyun.myinterface.impl.IUserMySQLImpl; public class Test1 { public static void main(String[] args) { // TODO Auto-generated method stub User user=new User(); user.username="admin"; user.password="root"; IUser test=new IUserMySQLImpl(); test.insert(user); } }
Test2.java
import com.xingyun.model.User; import com.xingyun.myinterface.IUser; import com.xingyun.myinterface.impl.IUserMySQLImpl; public class Test2 { public static void main(String[] args) { // TODO Auto-generated method stub User user=new User(); user.username="admin"; user.password="root"; IUser test=new IUserMySQLImpl(); test.insert(user); } }
我们可以发现Test1.java 和Test2.java 中调用方式都是这样:
IUser test=new IUserMySQLImpl(); test.insert(user);
但是假设后来项目中MySQL不想用了,想换Oracle 数据库了怎么办?
1.6 我们需要新写一个实现类 IUserOracleImpl.java
import com.xingyun.model.User; import com.xingyun.myinterface.IUser; public class IUserOracleImpl implements IUser{ @Override public void insert(User user) { // TODO Auto-generated method stub System.out.println("insert to Oracle"+user.toString()); } }
1.7 这很正常,但是我们之前有多处调用,所以我们将不得不修改Test1.java 和Test2.java,
Test1.java
import com.xingyun.model.User; import com.xingyun.myinterface.IUser; import com.xingyun.myinterface.impl.IUserOracleImpl; public class Test1 { public static void main(String[] args) { // TODO Auto-generated method stub User user=new User(); user.username="admin"; user.password="root"; IUser test=new IUserOracleImpl(); test.insert(user); } }
Test2.java
import com.xingyun.model.User; import com.xingyun.myinterface.IUser; import com.xingyun.myinterface.impl.IUserOracleImpl; public class Test2 { public static void main(String[] args) { // TODO Auto-generated method stub User user=new User(); user.username="admin"; user.password="root"; IUser test=new IUserOracleImpl(); test.insert(user); } }
试想下,假如Test1 ,Test 这类的调用方式有十几处的话,那么这么多地方都要改,我们是不是要累死?
那么如何优化呢?
2. 工厂模式手动实现方式
聪明的大牛做了这样的优化
2.1 实体类不变
public class User{ public String username; public String password; }
2.2 消息接口不变
import com.xingyun.model.User; public interface IUser { void insert(User user); }
2.3 一个实现类IUserMySQLImpl.java
import com.xingyun.model.User;
import com.xingyun.myinterface.IUser;
public class IUserMySQLImpl implements IUser{
@Override
public void insert(User user) {
// TODO Auto-generated method stub
System.out.println("insert to MySQL"+user.toString());
}
}
2.4 实现类 IUserOracleImpl.java 不变
import com.xingyun.model.User; import com.xingyun.myinterface.IUser; public class IUserOracleImpl implements IUser{ @Override public void insert(User user) { // TODO Auto-generated method stub System.out.println("insert to Oracle"+user.toString()); } }
2.5 新建了一个这样的类 IUserFactory.java
import com.xingyun.myinterface.IUser;
import com.xingyun.myinterface.impl.IUserMySQLImpl;
public class IUserFactory {
public static IUser getIUserImpl() {
return new IUserMySQLImpl();
}
}
2.6 最开始调用方式改变下
Test1.java
import com.xingyun.factory.IUserFactory; import com.xingyun.model.User; import com.xingyun.myinterface.IUser; public class Test1 { public static void main(String[] args) { // TODO Auto-generated method stub User user=new User(); user.username="admin"; user.password="root"; IUser test=IUserFactory.getIUserImpl(); test.insert(user); } }
Test2.java
import com.xingyun.factory.IUserFactory; import com.xingyun.model.User; import com.xingyun.myinterface.IUser; public class Test2 { public static void main(String[] args) { // TODO Auto-generated method stub User user=new User(); user.username="admin"; user.password="root"; IUser test=IUserFactory.getIUserImpl(); test.insert(user); } }
然后将Test1.java和Test2.java 中原来的调用方式
IUser test=new IUserMySQLImpl();
test.insert(user);
改成了这样:
IUser test=IUserFactory.getIUserImpl();
test.insert(user);
于是乎,我当需要将IUserMySQLImpl更换为IUserOracleImpl 的时候,我们只需要修改这个IUserFactory即可,Test1.java和Test2.java 任何调用的地方都不再需要改变。
import com.xingyun.myinterface.IUser; import com.xingyun.myinterface.impl.IUserOracleImpl; public class IUserFactory { public static IUser getIUserImpl() { return new IUserOracleImpl(); } }
你猜的没错,这就是Java 设计模式中著名的工厂模式,通过抽象出一个工厂,来屏蔽调用选择哪一种实现类的,这个问题丢给工厂类来处理切换哪一个实现类。
2. 工厂模式Spring IOC实现方式
Mark:https://www.cnblogs.com/cowboys/p/6638484.html
待续。。。