Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/386.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 具有继承的工厂方法模式的好方法_Java_Oop_Design Patterns_Factory_Factory Pattern - Fatal编程技术网

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语言中):

  • 现在,您只需要一个工厂,我也将使用一个类来实现DTO,因为您知道
    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];
        }
    }
    
  • 当然,有很多方法可以用不同的语言制作DTO,我不能详细介绍,这取决于你

  • 可以
    执行工厂方法静态,但如果要避免这种情况,必须使用某种类型的
    依赖项注入

    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);
        }
    }