когда использовать абстрактный шаблон фабрики? - PullRequest
5 голосов
/ 23 апреля 2010

Я хочу знать, когда нам нужно использовать абстрактный шаблон фабрики.

Вот пример, я хочу знать, если это необходимо.

UML

Выше приведен абстрактный шаблон фабрики, он рекомендован моим одноклассником.Следующее является моей собственной реализацией.Я не думаю, что необходимо использовать шаблон.

И вот некоторые основные коды:

    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, я работаю над созданием веб-сервиса

, веб-сервис содержит несколько алгоритмов для изменения файла в другой формат, например

: net.CreatePDF, net.CreateWord и т. д., он предоставляет клиенту два интерфейса: getAlgorithms и doProcess.

getAlogrithoms будет возвращать все идентификаторы алгоритмов, каждый идентификатор реализуется соответствующим алгоритмом.

Пользователь, который вызывает метод doProcess, также предоставит требуемый идентификатор алгоритма.

Весь алгоритм расширяет AbstractAlgorithm, который определяет метод run ().

Я используюAlogrithmsRepository для хранения всех алгоритмов (из

файла свойств, который конфигурирует конкретные java-классы алгоритмов через веб-администратор службы

). То есть интерфейс 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

когда сервер получит запрос такого типа, он получит конкретный экземпляр алгоритма в соответствии с параметром «attribute» (в этом запросе pdf) из AlgorithmRepostory.И вызовите метод:

AbstractAlgorithm algo=AlgorithmRepostory.getAlgo("pdf");
algo.start();

Затем пользователю будет отправлен файл PDF.

Кстати, в этом примере каждый алгоритм аналогичен sqlDao, AccessDao.Вот изображение:

Изображение дизайна

Теперь, нужно ли AlgorithmRepostory использовать абстрактную фабрику?

Ответы [ 3 ]

2 голосов
/ 23 апреля 2010

Основное различие между этими двумя подходами состоит в том, что верхний использует разные фабрики DAO для создания DAO, а нижний хранит набор DAO и возвращает ссылки на DAO в хранилище.

У нижнего подхода есть проблема, если нескольким потокам требуется одновременный доступ к одному и тому же типу DAO, поскольку соединения JDBC не синхронизированы.

Это можно исправить, если DAO реализует метод newInstance(), который просто создает и возвращает новый DAO.

abstract class AbstractDao {
    public abstract String getID();
    public abstract void insert();
    public abstract void update();
    public abstract AbstractDao newInstance();
}
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");}
    public AbstractDao newInstance() { return new SqlDao();}
}

Хранилище может использовать DAO в хранилище в качестве фабрик для DAO, возвращаемых хранилищем (которое в этом случае я бы переименовал в Factory), например:

public AbstractDao newDao(String id) {
    return daoMap.containsKey(id) ? daoMap.get(id).newInstance() : null;
}

Обновление

Что касается вашего вопроса, должен ли ваш веб-сервис реализовывать фабрику или он может использовать репозиторий, как вы описали? Опять же ответ зависит от деталей:

  • Для веб-сервисов это нормально ожидать нескольких одновременных клиентов
  • Следовательно, экземпляры, выполняющие процесс для двух клиентов не должен влияние друг друга
  • Это означает, что они не должны иметь общего состояния
  • Фабрика поставляет свежий экземпляр на каждый запрос, поэтому ни одно государство не является общим когда вы используете фабричный шаблон
  • Если (и только если) экземпляры в вашем хранилище без гражданства вашего веб-сервис также может использовать репозиторий, как вы описываете, для этого им, вероятно, нужно создать экземпляр другие объекты на самом деле выполнить процесс на основе запроса параметры переданы
2 голосов
/ 23 апреля 2010

Если вы попросите сравнить 2 дизайна из UML, 2-й API в UML имеет следующий недостаток:

  • вызывающая сторона должна явно указать тип DAO при вызове getDAO (). Вместо этого, вызывающий объект не должен заботиться о типе DAO, с которым он работает, если DAO соответствует интерфейсу. Первый дизайн позволяет вызывающей стороне просто вызвать createDAO () и получить интерфейс для работы. Таким образом, контроль над тем, что использовать, является более гибким, и вызывающая сторона не несет этой ответственности, что улучшает общую согласованность дизайна.
0 голосов
/ 24 апреля 2010

Абстрактная фабрика полезна, если вам нужно разделить несколько измерений выбора при создании чего-либо.

В типичном случае оконных систем вы хотите создать семейство виджетов для различных оконных систем, и высоздать конкретную фабрику для каждой оконной системы, которая создает виджеты, работающие в этой системе.

В вашем случае создания DAO, вероятно, будет полезно, если вам нужно создать семейство DAO для различных объектов в вашем домене,и хочу сделать версию «sql» и «access» для всей семьи.Я думаю, что это то, что пытается сделать ваш одноклассник, и если это то, что вы делаете, это, вероятно, будет хорошей идеей.

Если у вас меняется только одна вещь, это излишне.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...