Java 具有继承的工厂方法模式的好方法
假设我有以下类层次结构:Java 具有继承的工厂方法模式的好方法,java,oop,design-patterns,factory,factory-pattern,Java,Oop,Design Patterns,Factory,Factory Pattern,假设我有以下类层次结构: class abstract Parent{} class FirstChild extends Parent {} class SecondChild extends Parent {} 我想从每个子对象创建DTO对象: class abstract ParentDTO {} class FirstChildDTO extends ParentDTO{} class SecondChildDTO extends ParentDTO{} 我想我需要一种工厂方
class abstract Parent{}
class FirstChild extends Parent {}
class SecondChild extends Parent {}
我想从每个子对象创建DTO对象:
class abstract ParentDTO {}
class FirstChildDTO extends ParentDTO{}
class SecondChildDTO extends ParentDTO{}
我想我需要一种工厂方法,比如:
ParentDTO createFrom(Parent source);
在Java中,没有instanceof
检查和if/else语句,有什么好方法可以做到这一点吗
编辑:
此工厂方法不起作用:
public ParentDTO create(Parent source)
{
return _create(source);
}
private FirstChildDTO _create(FirstChild source)
{
return new FirstDTO();
}
private SecondChildDTO _create(SecondChild source)
{
return new SecondDTO();
}
private ParentDTO _create(Parent source)
{
return new ParentDTO();
}
它只会生成ParentDTO
s,原因如下:
Parent p = new FirstChild();
System.out.println(factory.create(p)); //ParentDTO
FirstChild f = new FirstChild();
System.out.println(factory.create(f)); //FirstChildDTO
这是一个相当复杂的问题。我会分几步解决这个问题
Parent
类应具有某种类型的接口,允许您的工厂识别DTO
对象应包含哪些数据,例如(在PHP语言中):
Parent
class DTOFactory
{
function createFromParent(Parent $parent)
{
return new DTO($parent);
}
}
class DTO
{
private $fields = [];
function __construct(Parent $parent)
{
foreach ($parent->getDataFields() as $field => $value) {
$this->fields[$field] = $value
}
}
function __get($field)
{
return $this->fields[$field];
}
}
可以
执行工厂方法静态,但如果要避免这种情况,必须使用某种类型的依赖项注入
:
class MyController
{
private $dtoFactory;
function __construct(DTOFactory $factory)
{
$this->dtoFactory = $factory;
}
function returnDTOAction()
{
$object = new FirstChild(); // or some other way to get your child;
return $this->factory->createFromParent($object);
}
}
class DIContainer
{
private $instances = [];
function get($className)
{
if (!is_object($this->instances[$className]) {
$this->instances[$className] = new $className;
}
return $this->instances[$className] = new $className;
}
}
$container = new DIContainer;
$controller = new MyController($container->get('DTOFactory'));
DI容器的示例,更好的示例具有自动依赖项解析,因此您只需像$Container->get('MyController')那样调用它们代码>并获得一个具有自动解析的依赖项的类,但我不会对此进行更详细的讨论,因为它们的实现严重依赖于语言,我只使用一个基本的实现
无论如何,希望这有帮助。如果您需要一些澄清,请随意评论。您可以将工厂方法直接编码到模型类中,并利用Java返回正确类型的DTO,例如:
public class Parent {
public ParentDTO createDTO() {
return new ParentDTO();
}
}
public class FirstChild extends Parent {
@Override
public FirstChildDTO createDTO() {
return new FirstChildDTO();
}
}
public class SecondChild extends Parent {
@Override
public SecondChildDTO createDTO() {
return new SecondChildDTO();
}
}
如果坚持使用工厂来创建DTO,可以使用简单的方法重载。示例如下:
public class Factory {
public ParentDTO createDTO(Parent parent) {
return new ParentDTO();
}
public FirstChildDTO createDTO(FirstChild firstChild) {
return new FirstChildDTO();
}
public SecondChildDTO createDTO(SecondChild SecondChild) {
return new SecondChildDTO();
}
}
public class Parent {
}
public class FirstChild extends Parent {
}
public class SecondChild extends Parent {
}
public class ParentDTO {
@Override
public String toString() {
return this.getClass().getSimpleName();
}
}
public class FirstChildDTO extends ParentDTO {
@Override
public String toString() {
return this.getClass().getSimpleName();
}
}
public class SecondChildDTO extends ParentDTO {
@Override
public String toString() {
return this.getClass().getSimpleName();
}
}
public class App {
public static void main(String[] args) {
Factory factory = new Factory();
ParentDTO parentDTO = factory.createDTO(new Parent());
System.out.println(parentDTO);
FirstChildDTO firstChildDTO = factory.createDTO(new FirstChild());
System.out.println(firstChildDTO);
SecondChildDTO secondChildDTO = factory.createDTO(new SecondChild());
System.out.println(secondChildDTO);
}
}
在my IDE中以Java应用程序的形式运行应用程序输出:
亲子关系到
第一个孩子到
SecondChildTo在动态语言中做得很好。也许我应该把这个问题限制在Java上:)我在Java方面没有那么丰富的经验,但我猜您使用HashMap
作为DTO
字段键值存储,就是这样。而且,据我所知,Java有很多DI容器实现,所以这也不会是一个问题。@Eternal1 Java是严格类型化的,HashMap并没有真正作为值对象的替代品引入。虽然您的建议可以很容易地在Java中实现,但理想情况下应该避免。它会产生你不想要/不需要的问题和头痛。@OlivierGrégoire谢谢,我记住了。对不起,这个想法是模型和DTO的去耦合。没问题。你应该选择最适合你的设计。请同时检查我的其他答案。这是我尝试的第一件事,但它不起作用。只有ParentDTO
实例是以这种方式创建的。我刚刚尝试过这种方法,它似乎对我有效。我将编辑我的答案,为您提供详细信息。你能在你的机器上试一下吗?是的,这很好用。我在尝试另一个案例,我正在用它更新问题。
public class Factory {
public ParentDTO createDTO(Parent parent) {
return new ParentDTO();
}
public FirstChildDTO createDTO(FirstChild firstChild) {
return new FirstChildDTO();
}
public SecondChildDTO createDTO(SecondChild SecondChild) {
return new SecondChildDTO();
}
}
public class Parent {
}
public class FirstChild extends Parent {
}
public class SecondChild extends Parent {
}
public class ParentDTO {
@Override
public String toString() {
return this.getClass().getSimpleName();
}
}
public class FirstChildDTO extends ParentDTO {
@Override
public String toString() {
return this.getClass().getSimpleName();
}
}
public class SecondChildDTO extends ParentDTO {
@Override
public String toString() {
return this.getClass().getSimpleName();
}
}
public class App {
public static void main(String[] args) {
Factory factory = new Factory();
ParentDTO parentDTO = factory.createDTO(new Parent());
System.out.println(parentDTO);
FirstChildDTO firstChildDTO = factory.createDTO(new FirstChild());
System.out.println(firstChildDTO);
SecondChildDTO secondChildDTO = factory.createDTO(new SecondChild());
System.out.println(secondChildDTO);
}
}