【问题标题】:Creating a single factory for unrelated objects为不相关的对象创建一个工厂
【发布时间】:2021-07-31 01:05:40
【问题描述】:

我有几个彼此不相关的类。

public class Apple
{
    
}

public class Giraffe
{
    
}

我可以为每个工厂创建一个单独的工厂,但我想获得如下结构。

Factory<Apple>.CreateSingle();

我想用上面的代码制作一个苹果。还有下面的代码;

Factory<Giraffe>.CreateCollection(20);

我想养 20 只长颈鹿。

为此,我创建了一个 IFactory 通用接口。

public interface IFactory<out T>
{
    T CreateSingle();
    IEnumerable<T> CreateCollection(int count);
}

每种类型都有一个工厂;

public class AppleFactory : IFactory<Apple>
{
    public Apple CreateSingle() =>
        new()
        {
           //some code
        };

    public IEnumerable<Apple> CreateCollection(int count)
    {
          // CreateSingle X count times, add to collection and return
    }
}

public class GiraffeFactory: IFactory<Giraffe>
{
    public Giraffe CreateSingle() =>
        new()
        {
           //some code
        };

    public IEnumerable<Giraffe> CreateCollection(int count)
    {
          // CreateSingle X count times, add to collection and return
    }
}

主厂长这样;

public static class Factory<T>
{
    private static IFactory<T> GetFactory()
    {
        if (typeof(T) == typeof(Apple)) return (IFactory<T>) new AppleFactory();
        if (typeof(T) == typeof(Giraffe)) return (IFactory<T>) new GiraffeFactory();
        return null;
    }
    public static T CreateSingle() => GetFactory().CreateSingle();
    public static IEnumerable<T> CreateCollection(int count) => GetFactory().CreateCollection(count);


}

这里的 if 结构看起来很丑。有没有一种方法可以让我以更清洁的方式做我想做的事情?这些天来,我正在努力学习设计模式,并强迫自己使用设计模式。由于这个原因,代码可能看起来不必要地混乱。这完全是实验性的。

[更新]

实际上,我用苹果和长颈鹿来表示数据库对象(订单、客户等)。在单元测试期间,我有时需要模拟这些对象。出于这个原因,我为每种对象类型编写了一个工厂。后来,我想如果我能把这些工厂聚集在一个工厂里。我还检查了抽象工厂方法,但不太合适。

我对代码做了一些更改。单独生成对象对每个对象都有一个单独的结构(因为它的属性不同)。但是在制作了一个作品之后,制作一个系列对所有人来说都是一样的。为此,我将集合生产方式转移到了总厂。

另外,我使用反射在主工厂内选择合适的工厂进行生产。

再一次,我做这一切只是为了实验目的。我没有得到任何有用的结果。我认为无论如何最好使用单独的工厂。

public static class Factory<T>
{
    private static IFactory<T> _factory;
    private static IFactory<T> SetFactory()
    {
        var type = typeof(IFactory<T>);
        var desiredFactory = AppDomain.CurrentDomain.GetAssemblies()
            .SelectMany(s => s.GetTypes())
            .First(p => type.IsAssignableFrom(p));
        if (_factory == null || desiredFactory != _factory.GetType())
        {
            _factory=(IFactory<T>)Activator.CreateInstance(desiredFactory);
        }
        return _factory;
    }
    public static T CreateSingle() => SetFactory().CreateSingle();

    public static IEnumerable<T> CreateEnumerable(int count)
    {
       // I removed creating collection method from each factory to here
    }

【问题讨论】:

  • 你为什么想要Factory of Factories。只要符合factory Interface,您就可以拥有单独的工厂。现在如果要添加新工厂,则需要在此处编写新的 IF 语句,这是不可取的,因为它正在更改现有代码,这违反了Close for changes Open for extension 原则。无论如何,您似乎事先知道类型,因此您可以直接致电工厂。
  • 看起来大多数这些东西都没有存在的理由。或者,至少你还没有提供一个。具有createApple()createGiraffe() 等的接口有什么问题?
  • 实际上我用苹果和长颈鹿来表示数据库对象(订单、客户等)。在单元测试期间,我有时需要模拟这些对象。出于这个原因,我为每种对象类型编写了一个工厂。后来,我想如果我能把这些工厂聚集在一个工厂里。我还检查了抽象工厂方法,但它不太适合。我更新了主帖。非常感谢您的回答。

标签: design-patterns


【解决方案1】:

这可以使用供应商和方法引用来创建一些干净的代码来实现。如果需要,您可以进行一些修改以使用 create() 方法而不是对构造函数的方法引用。我在这里保持简单。

abstract class Animal<T> implements Supplier<Animal> {
}

public abstract class Fruit<T> implements Supplier {
}

public class Giraffe<T> extends Animal{
    @Override
    public Giraffe get(){
        System.out.println("Create Giraffe");
        return new Giraffe();
    }
}


public class Apple extends Fruit{
    @Override
    public Apple get(){
        System.out.println("Create Apple");
        return new Apple();
    }
}


public abstract class AbstractFactory<T>{
    abstract T createEntity(String action);
}


class AnimalFactory<T extends Animal> extends AbstractFactory<T>{

    private  final Map<String, Supplier<T>> map =
            Map.of(
                    "Giraffe", new Giraffe()
//                    "Lion", Lion::new
            );
    @Override
    T createEntity(String action){
        System.out.println("Return Animal Factory");
        return (T) map.get(action);
     }
}

class FruitFactory<T extends Fruit> extends AbstractFactory<T>{

    private final Map<String, Supplier<T>> map =
            Map.of(
                    "Apple", new Apple()
//                    "Orange", Orange::new
            );
    @Override
    T createEntity(String action){
        System.out.println("Return Fruit Factory");
        return (T) map.get(action);
    }
}


public class TestFactory {
    public static void main(String[] args) {
        AnimalFactory<Giraffe> animalFactory = new AnimalFactory<>();
        Animal giraffe = animalFactory.createEntity("Giraffe");
        System.out.println("Created giraffe::" + giraffe);

        FruitFactory<Apple> fruitFactory = new FruitFactory<>();
        Apple apple = fruitFactory.createEntity("Apple");
        System.out.println("Created apple::" + apple);

    }
}

//ouput
Return Animal Factory
Created giraffe::Giraffe@63961c42
Return Fruit Factory
Created apple::Apple@77459877

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-05
    • 1970-01-01
    • 2020-08-17
    • 1970-01-01
    相关资源
    最近更新 更多