什么时候使用抽象工厂模式?
我想知道什么时候我们需要使用抽象工厂模式。
这是一个例子,我想知道是否有必要。
上面是抽象工厂模式,是我同学推荐的。 以下是我自己的实现。我认为没有必要使用该模式。
下面是一些核心代码:
package net;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
public class Test {
public static void main(String[] args) throws IOException, InstantiationException, IllegalAccessException, ClassNotFoundException {
DaoRepository dr=new DaoRepository();
AbstractDao dao=dr.findDao("sql");
dao.insert();
}
}
class DaoRepository {
Map<String, AbstractDao> daoMap=new HashMap<String, AbstractDao>();
public DaoRepository () throws IOException, InstantiationException, IllegalAccessException, ClassNotFoundException {
Properties p=new Properties();
p.load(DaoRepository.class.getResourceAsStream("Test.properties"));
initDaos(p);
}
public void initDaos(Properties p) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
String[] daoarray=p.getProperty("dao").split(",");
for(String dao:daoarray) {
AbstractDao ad=(AbstractDao)Class.forName(dao).newInstance();
daoMap.put(ad.getID(),ad);
}
}
public AbstractDao findDao(String id) {return daoMap.get(id);}
}
abstract class AbstractDao {
public abstract String getID();
public abstract void insert();
public abstract void update();
}
class SqlDao extends AbstractDao {
public SqlDao() {}
public String getID() {return "sql";}
public void insert() {System.out.println("sql insert");}
public void update() {System.out.println("sql update");}
}
class AccessDao extends AbstractDao {
public AccessDao() {}
public String getID() {return "access";}
public void insert() {System.out.println("access insert");}
public void update() {System.out.println("access update");}
}
而 Test.properties 的内容只有一行:
dao=net.SqlDao,net.SqlDao
所以任何人都可以告诉我这个适应是否有必要?
-------------------添加以下内容是为了解释真正的适合--------------
我使用 Dao 的例子是因为这很常见,任何人都知道。
事实上,我现在所做的工作与DAO无关,我正在构建一个Web
服务,该Web服务包含一些将文件更改为其他格式的算法,
例如:net.CreatePDF、net.CreateWord等,它向客户端暴露了两个接口:getAlgorithms 和 doProcess。
getAlogrithoms 将返回所有算法的 id,每个 id 都与 相应的算法。
调用doProcess方法的用户也会提供他想要的算法id。
所有算法都扩展了 AbstractAlgorithm,它定义了 run() 方法。
我使用 AlogrithmsRepository 来存储所有算法(来
自由 Web 服务管理员配置算法的具体 java 类的属性文件
)。也就是说,Web 服务公开的接口 DoProcess
由具体算法执行。
我可以举一个简单的例子: 1)用户发送 getAlgorithms 请求:
http://host:port/ws?request=getAlgorithms
然后用户将获得嵌入在 xml 中的算法列表。
<AlgorithmsList>
<algorithm>pdf</algorithm>
<algorithm>word<algorithm>
</AlgorithmsList>
2)用户向服务器发送DoProcess:
http://xxx/ws?request=doProcess&alogrithm=pdf&file=http://xx/Test.word
当服务器收到此类请求时,会根据“算法”参数(本次请求中为pdf)从AlgorithmRepostory中获取具体的算法实例。并调用该方法:
AbstractAlgorithm algo=AlgorithmRepostory.getAlgo("pdf");
algo.start();
然后一个pdf文件将发送给用户。
顺便说一句,在这个例子中,每个算法都类似于sqlDao,AccessDao。 这是图片:
现在,AlgorithmRepostory 是否需要使用 Abstract工厂?
I want to know when we need to use the abstract factory pattern.
Here is an example,I want to know if it is necessary.
THe above is the abstract factory pattern, it is recommended by my classmate.
THe following is myown implemention. I do not think it is necessary to use the pattern.
And the following is some core codes:
package net;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
public class Test {
public static void main(String[] args) throws IOException, InstantiationException, IllegalAccessException, ClassNotFoundException {
DaoRepository dr=new DaoRepository();
AbstractDao dao=dr.findDao("sql");
dao.insert();
}
}
class DaoRepository {
Map<String, AbstractDao> daoMap=new HashMap<String, AbstractDao>();
public DaoRepository () throws IOException, InstantiationException, IllegalAccessException, ClassNotFoundException {
Properties p=new Properties();
p.load(DaoRepository.class.getResourceAsStream("Test.properties"));
initDaos(p);
}
public void initDaos(Properties p) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
String[] daoarray=p.getProperty("dao").split(",");
for(String dao:daoarray) {
AbstractDao ad=(AbstractDao)Class.forName(dao).newInstance();
daoMap.put(ad.getID(),ad);
}
}
public AbstractDao findDao(String id) {return daoMap.get(id);}
}
abstract class AbstractDao {
public abstract String getID();
public abstract void insert();
public abstract void update();
}
class SqlDao extends AbstractDao {
public SqlDao() {}
public String getID() {return "sql";}
public void insert() {System.out.println("sql insert");}
public void update() {System.out.println("sql update");}
}
class AccessDao extends AbstractDao {
public AccessDao() {}
public String getID() {return "access";}
public void insert() {System.out.println("access insert");}
public void update() {System.out.println("access update");}
}
And the content of the Test.properties is just one line:
dao=net.SqlDao,net.SqlDao
So any ont can tell me if this suitation is necessary?
-------------------The following is added to explain the real suitation--------------
I use the example of Dao is beacuse it is common,anyone know it.
In fact,what I am working now is not related to the DAO,I am working to build a Web
service,the web serivce contains some algorithms to chang a file to other format,
For example:net.CreatePDF,net.CreateWord and etc,it expose two interfaces to client:getAlgorithms and doProcess.
The getAlogrithoms will return all the algorithms's ids,each id is realted to the
corresponding algorithm.
User who call the doProcess method will also provide the algorithm id he wanted.
All the algorithm extends the AbstractAlgorithm which define a run() method.
I use a AlogrithmsRepository to store all the algorithms(from
the properties file which config the concrete java classes of the algorithms by the web
service admin).That's to say, the interface DoProcess exposed by the web service is
executed by the concrete alogrithm.
I can give a simple example:
1)user send getAlgorithms request:
http://host:port/ws?request=getAlgorithms
Then user will get a list of algorithms embeded in a xml.
<AlgorithmsList>
<algorithm>pdf</algorithm>
<algorithm>word<algorithm>
</AlgorithmsList>
2)user send a DoProcess to server by:
http://xxx/ws?request=doProcess&alogrithm=pdf&file=http://xx/Test.word
when the server recieve this type of requst,it will get the concrete algorithm instance according to the "algorithm" parameter(it is pdf in this request) from the AlgorithmRepostory. And call the method:
AbstractAlgorithm algo=AlgorithmRepostory.getAlgo("pdf");
algo.start();
Then a pdf file will be sent to user.
BTW,in this example, the each algorithm is similar to the sqlDao,AccessDao.
Here is the image:
Now,does the AlgorithmRepostory need to use the Abstract Factory?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
两种方法之间的主要区别在于,顶部方法使用不同的 DAO 工厂来创建 DAO,而底部方法存储一组 DAO 并返回对存储库中 DAO 的引用。
如果多个线程需要同时访问同一类型的 DAO,而 JDBC 连接不同步,那么底层方法就会出现问题。
这可以通过让 DAO 实现 newInstance() 方法来解决,该方法只需创建并返回一个新的 DAO。
存储库可以使用存储库中的 DAO 作为存储库返回的 DAO 的工厂(在这种情况下我将其重命名为 Factory),如下所示:
更新
至于您的问题,您的 Web 服务是否应该实现一个工厂或者它可以像你描述的那样使用存储库吗?同样,答案取决于细节:
期望有多个并发客户端
两个客户的流程不得
互相影响
每个请求,因此不会共享任何状态
当您使用工厂模式时
存储库是无状态的
网络服务也可以使用
如您所描述的存储库,为此
他们可能需要实例化
实际执行的其他对象
根据请求进行处理
传递的参数
The main difference between the two approaches is that the top one uses different DAO factories to create DAO's while the bottom one stores a set of DAO's and returns references to the DAO's in the repository.
The bottom approach has a problem if multiple threads need access to the same type of DAO concurently as JDBC connections are not synchronised.
This can be fixed by having the DAO implement a
newInstance()
method which simply creates and returns a new DAO.The repository can use the DAO's in the repository as factories for the DAO's returned by the Repository (which I would rename to Factory in that case) like this:
Update
As for your question should your web-service implement a factory or can it use the repository like you described? Again the answer depends on the details:
expect multiple concurrent clients
process for two clients must not
influence eachother
every request, so no state is shared
when you use a factory pattern
repository are stateless your
web-service can also use the
repository as you describe, for this
they probably need to instantiate
other objects to actually execute the
process based on the request
parameters passed
如果您要求比较 UML 的 2 个设计,UML 上的第二个 API 具有以下缺点:
If you ask to compare 2 designs from UML, 2nd API on UML have following disadvantage:
如果您需要在创建某些内容时分离多个维度的选择,则抽象工厂非常有用。
在窗口系统的常见示例中,您想要为各种窗口系统创建一系列小部件,并且为每个窗口系统创建一个具体工厂,以创建在该系统中工作的小部件。
在构建 DAO 的情况下,如果您需要为域中的各种实体创建一系列 DAO,并且想要为整个系列创建一个“sql”版本和一个“access”版本,那么它可能会很有用。我认为这就是你的同学想要表达的观点,如果这就是你正在做的事情,那可能是个好主意。
如果只有一件事发生变化,那就太过分了。
Abstract Factory is useful if you need to separate multiple dimensions of choices in creating something.
In the common example case of windowing systems, you want to make a family of widgets for assorted windowing systems, and you create a concrete factory per windowing system which creates widgets that work in that system.
In your case of building DAOs, it is likely useful if you need to make a family of DAOs for the assorted entities in your domain, and want to make a "sql" version and an "access" version of the entire family. This is I think the point your classmate is trying to make, and if that's what you're doing it's likely to be a good idea.
If you have only one thing varying, it's overkill.