工厂模式学习

来源:互联网 发布:阿里云如何解析域名 编辑:程序博客网 时间:2024/06/05 00:11

以下是我学习尚学堂视频DRP项目关于工厂模式的总结,继续更新中...

1.最原始的工厂模式:--业务逻辑无接口:   drp_my1.5.3.4

1.Dao层接口

public interface ItemDao {

public void addItem(Connection conn,Item item);

}

2.Dao实现:

public class ItemDao4MySqlImpl implements ItemDao {

public void addItem(Connection conn, Item item) {

}

}

3.工厂接口:

public interface ItemDaoFactory {

public ItemDao createItemDao();

}

4.工厂实现:

public class ItemDao4MySqlFactory implements ItemDaoFactory {

public ItemDao createItemDao() {

return new ItemDao4MySqlImpl();

}

}

5.业务逻辑:

public class ItemManager {

private ItemDaoFactory itemDaoFactory ; 

private static ItemManager instance = new ItemManager();

private ItemManager() {

itemDaoFactory = new ItemDao4MySqlFactory();

}

public static ItemManager getInstance () {

return instance;

}

public void addItem(Item item) {

Connection conn = DB.getConnection();

this.itemDaoFactory.createItemDao().addItem(conn, item);

DB.close(conn);

}

}

总结:业务逻辑类没有接口,采用单例模式创建.当初始化业务逻辑类时,创建出具体的工厂实现类.

缺点:如果要更换别的数据库,需要在构造函数里手动更改具体的工厂实现类.

_____________________________________________________________________________________

2.对业务逻辑层进一步改进: --读取配置文件,放在构造函数里:  drp_my1.5.3.4

1.Dao层接口

public interface ItemDao {

public void addItem(Connection conn,Item item);

}

2.Dao实现:

public class ItemDao4MySqlImpl implements ItemDao {

public void addItem(Connection conn, Item item) {

}

}

3.工厂接口:

public interface ItemDaoFactory {

public ItemDao createItemDao();

}

4.工厂实现:

public class ItemDao4MySqlFactory implements ItemDaoFactory {

public ItemDao createItemDao() {

return new ItemDao4MySqlImpl();

}

}

5.业务逻辑:

public class ItemManager {

private ItemDaoFactory itemDaoFactory ; 

private static ItemManager instance = new ItemManager();

private ItemManager() {

Properties props = this.loadProp();

String className = props.getProperty("item-dao-factory");

itemDaoFactory = (ItemDaoFactory)Class.forName(className).newInstance();

}

public static ItemManager getInstance () {

return instance;

}

public void addItem(Item item) {

Connection conn = DB.getConnection();

this.itemDaoFactory.createItemDao().addItem(conn, item);

DB.close(conn);

}

}

改进:初始化业务逻辑类时创建出的工厂实现类由读取配置文件动态生成.

只要更改配置文件就能为我们创建出需要的工厂实现类.

缺点:读取配置文件的代码都放在构造函数里.应该被分离出来.

_____________________________________________________________________________________

3.标准的工厂模式:--(需要传Connection)   drp_my1.7(ItemManagerImpl)

1.Dao层接口

public interface ItemDao {

public void addItem(Connection conn,Item item);

}

2.Dao实现:

public class ItemDao4MySqlImpl implements ItemDao {

public void addItem(Connection conn, Item item) {

}

}

3.工厂接口:

public interface ItemDaoFactory {

public ItemDao createItemDao();

}

4.工厂实现:

public class ItemDao4MySqlFactory implements ItemDaoFactory {

public ItemDao createItemDao() {

return new ItemDao4MySqlImpl();

}

}

5.业务逻辑接口:

public interface ItemManager {

public void addItem(Item item);

}

6.业务逻辑实现:

public class ItemManagerImpl implements ItemManager{

private ItemDaoFactory itemDaoFactory ; 

public ItemManagerImpl(ItemDaoFactory itemDaoFactory) {

this.itemDaoFactory = itemDaoFactory;

}

public void addItem(Item item) {

Connection conn = DB.getConnection();

this.itemDaoFactory.createItemDao().addItem(conn, item);

DB.close(conn);

}

}

7.读取配置文件: InitServlet

public class InitServlet extends HttpServlet {

public void init() {

String className = props.getProperty("item-dao-factory");

ItemDaoFactory itemDaoFactory = (ItemDaoFactory)Class.forName(className).newInstance();

ItemManager itemManager = new ItemManagerImpl(itemDaoFactory);

this.getServletContext().setAttribute(ItemManager.class.getName(), itemManager);

改进:分离出了业务逻辑接口和实现.当Web容器启动时,读取配置文件,把具体的工厂创建出来,

传给业务逻辑实现类,同时暴露给JSP的是业务逻辑接口.

缺点:工厂类太多了,每个工厂都有实现类.工厂泛滥.

________________________________________________________________________________________________

4.简化了的工厂1:只有一个工厂类,Dao层不传递Connection  drp_my1.7(FlowCard)

1.Dao层接口

public interface FlowCardDao {

public void addFlowCardMaster(FlowCard flowCard)

}

2.Dao实现:

public class FlowCardDao4MySqlImpl implements FlowCardDao {

public void addFlowCardMaster(FlowCard flowCard){

Connection conn = ConnectionManager.getConnection();

.......

//close pstmt,don't close connection

}

}

3.工厂类:

public class FlowCardDaoFactory {

private static FlowCardDaoFactory instance = new FlowCardDaoFactory();

private FlowCardDaoFactory() {}

public static FlowCardDaoFactory getInstance() {

return instance;

}

public FlowCardDao createFlowCardDao() {

return new FlowCardDao4MySqlImpl(); //直接创建产品,写死了.

}

}

4.业务逻辑接口:

public interface FlowCardService {

public void addFlowCard(FlowCard flowCard);

}

5.业务逻辑实现:

public class FlowCardServiceImpl implements FlowCardService {

private FlowCardDao flowCardDao;

public FlowCardServiceImpl(FlowCardDao flowCardDao) {

this.flowCardDao = flowCardDao;

}

public void addFlowCard(FlowCard flowCard){

Connection conn = ConnectionManager.getConnection();

conn.setAutoCommit(false);

//因为依赖于Dao接口,直接调用Dao层的方法

flowCardDao.addFlowCardMaster(flowCard);

conn.commit();

conn.rollback();

conn.setAutoCommit(true);

ConnectionManager.closeConnection();

}

}

6.读取配置文件: InitServlet

public class InitServlet extends HttpServlet {

public void init() {

FlowCardDao flowCardDao = FlowCardDaoFactory.getInstance().createFlowCardDao();

FlowCardService flowCardService = new FlowCardServiceImpl(flowCardDao);

this.getServletContext().setAttribute("flowCardService", flowCardService);

}

}

7.封装Connection:

public class ConnectionManager {

private static ThreadLocal connectionHolder = new ThreadLocal();

public static Connection getConnection() {

Connection conn = (Connection)connectionHolder.get();

if (conn == null) {

try {

Class.forName("com.mysql.jdbc.Driver");

conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/drp", "root", "root");

connectionHolder.set(conn);

}

}

return conn;

}

总结:工厂类直接来创建产品.业务逻辑实现类不再依赖与工厂接口,依赖于Dao接口,

同业务层依赖于工厂接口一样,传给业务层构造函数的是Dao接口,但是需要new出具体的Dao产品.

 

_____________________________________________________________________________________________

4.简化工厂2:动态代理统一管理事务.在业务逻辑方法中不再管理事务,业务层依赖于Dao.   drp_my1.7

public Object invoke(Object proxy, Method method, Object[] args){

Object ret = null;

Connection conn = ConnectionManager.getConnection();

conn.setAutoCommit(false);

ret = method.invoke(this.targetObject, args);

conn.commit();

conn.rollback();

ConnectionManager.closeConnection();

return ret;

}

5.业务逻辑方法:

public void addFlowCard(FlowCard flowCard){

//因为依赖于Dao接口,直接调用Dao层的方法

flowCardDao.addFlowCardMaster(flowCard);

}

6.读取配置文件: InitServlet

public class InitServlet extends HttpServlet {

public void init() {

FlowCardDao flowCardDao = FlowCardDaoFactory.getInstance().createFlowCardDao();

//FlowCardService flowCardService = new FlowCardServiceImpl(flowCardDao);

TransactionHandler transactionHandler = new TransactionHandler();

FlowCardService flowCardService = (FlowCardService)

transactionHandler.newProxy(new FlowCardServiceImpl(flowCardDao));

this.getServletContext().setAttribute(FlowCardService.class.getName(), flowCardService);

}

}

 

动态代理:对实现了接口的目标对象FlowCardServiceImpl生成代理对象.

________________________________________________________________________________________

4.简化的工厂3:通过读取配置文件:业务层依赖于Dao接口  drp_my1.7.1

1.Dao层接口

public interface FlowCardDao {

public void addFlowCardMaster(FlowCard flowCard)

}

2.Dao实现:

public class FlowCardDao4MySqlImpl implements FlowCardDao {

public void addFlowCardMaster(FlowCard flowCard){

Connection conn = ConnectionManager.getConnection();

.......

//close pstmt,don't close connection

}

}

3.工厂类:

//public class FlowCardDaoFactory {

//private FlowCardDao flowCardDao;

//

//public FlowCardDaoFactory(FlowCardDao flowCardDao) {

//this.flowCardDao = flowCardDao;

//}

//}

4.业务逻辑接口:

public interface FlowCardService {

public void addFlowCard(FlowCard flowCard);

}

5.业务逻辑实现:

public class FlowCardServiceImpl implements FlowCardService {

private FlowCardDao flowCardDao;

public FlowCardServiceImpl(FlowCardDao flowCardDao) {

this.flowCardDao = flowCardDao;

}

public void addFlowCard(FlowCard flowCard){

//因为依赖于Dao接口,直接调用Dao层的方法

flowCardDao.addFlowCardMaster(flowCard);

}

}

6.读取配置文件: InitServlet

public class InitServlet extends HttpServlet {

public void init() {

String className = props.getProperty("flowCardDao");

FlowCardDao flowCardDao = (FlowCardDao)Class.forName(className).newInstance();

//flowCardDao = (FlowCardDao)new FlowCardDaoFactory(flowCardDao);

FlowCardService flowCardService = new FlowCardServiceImpl(flowCardDao);

this.getServletContext().setAttribute("flowCardService", flowCardService);

}

}

 

因为业务层实现类依赖于Dao接口,初始化的时候读取出来的是具体的Dao,转换为Dao接口.

直接传给业务层的构造函数.而不必经过传给Dao工厂类这一步.这样把工厂类删掉也行的.

这些想想:工厂的作用是什么,去掉工厂类,工厂创建产品的行为被转换为直接读取出Dao实现类,

转换为Dao接口,传给业务层构造函数.除非业务层依赖的是工厂.而不是Dao.这样工厂就有存在的必要了.

 

存在工厂,比如用抽象工厂,一个工厂可以创建出多个产品 ,不再是单一系列产品,比如:UserDao,ItemDao.

业务层依赖于工厂,业务的方法通过调用工厂的方法得到createUserDao(),createItemDao()...再调用Dao方法.

 

动态代理InitServlet的配置:

String className = props.getProperty("flowCardDao");

FlowCardDao flowCardDao = (FlowCardDao)Class.forName(className).newInstance();

//flowCardDao = (FlowCardDao)new FlowCardDaoFactory(flowCardDao);

//FlowCardService flowCardService = new FlowCardServiceImpl(flowCardDao);

TransactionHandler transactionHandler = new TransactionHandler();

FlowCardService flowCardService = (FlowCardService)

transactionHandler.newProxy(new FlowCardServiceImpl(flowCardDao));

this.getServletContext().setAttribute("flowCardService", flowCardService);

_____________________________________________________________________________________________

4.简化的工厂模式4:业务层依赖于工厂,读取配置文件:   drp_my1.7.1.2

1.Dao层接口

public interface FlowCardDao {

public void addFlowCardMaster(FlowCard flowCard)

}

2.Dao实现:

public class FlowCardDao4MySqlImpl implements FlowCardDao {

public void addFlowCardMaster(FlowCard flowCard){

Connection conn = ConnectionManager.getConnection();

.......

//close pstmt,don't close connection

}

}

3.工厂类:

public class FlowCardDaoFactory {

private FlowCardDao flowCardDao;

public FlowCardDaoFactory(FlowCardDao flowCardDao) {

this.flowCardDao = flowCardDao;

}

public FlowCardDao createFlowCardDao() {

return flowCardDao;

}

}

4.业务逻辑接口:

public interface FlowCardService {

public void addFlowCard(FlowCard flowCard);

}

5.业务逻辑实现:

public class FlowCardServiceImpl implements FlowCardService {

private FlowCardDaoFactory flowCardDaoFactory;

public FlowCardServiceImpl(FlowCardDaoFactory flowCardDaoFactory) {

this.flowCardDaoFactory = flowCardDaoFactory;

}

public void addFlowCard(FlowCard flowCard){

//因为依赖于工程,通过工厂创建产品 ,再调用到Dao层的方法

flowCardDaoFactory.createFlowCardDao().addFlowCardMaster(flowCard);

}

}

6.读取配置文件: InitServlet

public class InitServlet extends HttpServlet {

public void init() {

String classFlowCardDao = propFlowCard.getProperty("flowCardDao");

FlowCardDao flowCardDao = (FlowCardDao)Class.forName(classFlowCardDao).newInstance();

//把创建好的具体Dao传给工厂类的构造器

FlowCardDaoFactory flowCardDaoFactory = (FlowCardDaoFactory)new FlowCardDaoFactory(flowCardDao);

//业务层依赖于工厂,把工厂传给业务层的构造器

FlowCardService flowCardService = new FlowCardServiceImpl(flowCardDaoFactory);

this.getServletContext().setAttribute("flowCardService", flowCardService);

}

}

 

把Dao接口传给工厂的构造函数.而不是传给业务层的构造函数.

存在工厂,就是通过业务层访问的是工厂,而不是把Dao接口直接开放给业务层.

业务层调用Dao层的方法必须先通过工厂创建出产品,然后调用Dao层的方法.

 

动态代理InitServlet的配置:  drp_my1.7.1.3:

String className = props.getProperty("flowCardDao");

FlowCardDao flowCardDao = (FlowCardDao)Class.forName(className).newInstance();

FlowCardDaoFactory FlowCardDaoFactory = (FlowCardDao)new FlowCardDaoFactory(flowCardDao);

//FlowCardService flowCardService = new FlowCardServiceImpl(flowCardDaoFactory);

TransactionHandler transactionHandler = new TransactionHandler();

FlowCardService flowCardService = (FlowCardService)

transactionHandler.newProxy(new FlowCardServiceImpl(flowCardDaoFactory));

this.getServletContext().setAttribute("flowCardService", flowCardService);

___________________________________________________________________________________________

总结工厂模式:

1.工厂模式:由工厂的实现类来创建出Dao实现产品,

业务层依赖于工厂接口.调用工厂接口的方法得到Dao接口,调用Dao接口的方法完成与Dao层的交互.

但是需要创建的工厂必须是具体的工厂实现.因为业务层实际上是跟某个具体工厂交互的.(具体的东西了)

只不过通过工厂接口,更通用些,移植更方便.

 

2.读取配置文件放在构造函数里:

采用单例模式,因为读取配置文件在私有构造函数里,读取出来的就是具体的实现类,转换为工厂接口即可.

 

3.分离出读取配置文件,业务层抽取出接口:

因为把读取配置文件的操作分离出放在InitServlet里,所以读取出来的是具体的实现类,需要转换为接口,

同时为业务层提供公共的构造函数,传给构造函数.因为业务层需要的工厂接口.

传递给业务层构造函数的只要是工厂的接口就可以,因为是面向接口编程,不需要知道具体的工厂实现类.

 

ItemManagerImpl的依赖关系是ItemDaoFactory工厂接口.拿到ItemDaoFactory,

调用ItemDaoFactory的方法,返回的是Dao层的接口,再调用Dao层的方法.

ItemManagerImpl需要具体的工厂实现类,才能调用具体的Dao层实现类的方法.

 

4.简化的工厂模式,没有工厂实现类:

4.1:工厂的方式是单例,没有读取配置文件,业务层依赖于Dao接口,不是依赖于工厂.

工厂类直接来创建产品.因为没有了具体的工厂实现类,就不能把创建好的工厂实现类转换为接口

传给业务逻辑实现类,然后调用Dao层的方法来完成业务逻辑处理.

4.2:通过动态代理管理事务.

4.3:读取配置文件创建具体的Dao,业务层依赖于Dao接口

把创建好具体的Dao传给业务层的构造器,业务层直接调用业务层的Dao方法.

4.4:读取配置文件创建具体的Dao,业务层依赖于工厂:

不同的是需要把具体的Dao传给工厂的构造器,工厂需要有一个创建产品的方法.

业务层调用工厂时先创建出Dao产品,再调用Dao层的方法.

 

还要注意工厂接口不能被new出来,只有具体的实现才能被new出来.

抽象的东西都是不能new的只有具体的东西才行.

 

 

原创粉丝点击