这是文章
https://www.codeproject.com/Articles/328373/Understanding-and-Implementing-Abstract-Factory-Pa
我不知道为什么我们需要像客户IPhoneFactory
这样的抽象工厂,我们不能像
class PhoneTypeChecker
{
ISmart sam;
IDumb htc;
//IPhoneFactory factory; get rid of this abstract factory
MANUFACTURERS manu;
...
public void CheckProducts()
{
switch (manu)
{
case MANUFACTURERS.SAMSUNG:
Console.WriteLine(new SamsungFactory().GetSmart().Name());
Console.WriteLine(new SamsungFactory().GetDumb().Name());
break;
case MANUFACTURERS.HTC:
Console.WriteLine(new HTCFactory().GetSmart().Name());
Console.WriteLine(new HTCFactory().GetDumb().Name());
break;
case MANUFACTURERS.NOKIA:
Console.WriteLine(new NokiaFactory().GetSmart().Name());
Console.WriteLine(new NokiaFactory().GetDumb().Name());
break;
}
Console.WriteLine(manu.ToString() + ":\nSmart Phone: " +
factory.GetSmart().Name() + "\nDumb Phone: " + factory.GetDumb().Name());
}
}
我唯一想到使用IPhoneFactory
的地方是,我们需要从具体的工厂类中获得两种不同的类型(智能和哑巴),但是它只保存了一些击键,对吗?
答案 0 :(得分:2)
与您链接的文章存在一个中心问题,这意味着它没有提供一个很好的示例来说明如何使用抽象工厂来使应用程序更具扩展性:
问题在于enum Manufacturers
和class PhoneTypeChecker.CheckProducts
都必须了解所有类型的制造商。这几乎完全破坏了抽象工厂模式的目的(除非您将CheckProducts()
解释为“抽象工厂工厂”方法-在这种情况下为welcome to Enterprise Java hell。
...但是,如果我们对组成进行一些调整,优势将变得显而易见。
首先,删除enum MANUFACTURER
(无论如何都不应该大写)和CheckProducts
,然后将其替换为IManufacturerRepository
。
IManufacturerRepository
应该只有一个实现(或用于测试/模拟的单独实现)。
public interface IManufacturerRepository
{
List<IManufacturer> GetManufacturers();
}
public interface IManufacturer
{
String Name { get; }
IPhoneFactory PhoneFactory { get; } // <-- this is the abstract factory
}
然后PhoneTypeChecker
可以通过构造函数参数接收IManufacturer
:
PhoneTypeChecker
内部没有有意义的实例状态突变,PhoneTypeChecker
也不代表由抽象类型或接口表示的任何类型的操作-最好这样做CheckProducts
一种static
方法,该方法接受IManufacturer
作为参数。)CheckProducts
方法确实改变了PhoneTypeChecker
的状态(通过设置factory
,sam
,htc
),但是这是一个糟糕的设计-因为它实际上只是在初始化自身,应该在构造函数内部完成-但我离题了。无论如何:
public class PhoneTypeChecker
{
private readonly IManufacturer mfg;
public PhoneTypeChecker( IManufacturer mfg )
{
this.mfg = mfg ?? throw new ArgumentNullExceptio(nameof(mfg));
}
public void CheckProducts()
{
Console.WriteLine( this.mfg.Name + ":\nSmart Phone: " +
this.mfg.PhoneFactory.GetSmart().Name() + "\nDumb Phone: " + this.mfg.PhoneFactory.GetDumb().Name() );
}
}
然后将Main
方法重做为:
static void Main(string[] args)
{
IManufacturerRepository repo = new ActualIManufacturerRepository();
List<IManufacturer> mfgs = repo.GetManufacturers();
PhoneTypeChecker checker = new PhoneTypeChecker( mfgs.Single( m => m.Name == "Samsung" ) );
checker.CheckProducts();
Console.ReadLine();
checker = new PhoneTypeChecker( mfgs.Single( m => m.Name == "HTC" ) );
checker.CheckProducts();
Console.ReadLine();
checker = new PhoneTypeChecker( mfgs.Single( m => m.Name == "Nokia" ) );
checker.CheckProducts();
Console.Read();
}
此示例还有其他问题-因此,请勿以该示例为例来编写结构良好或具有生产质量的代码。
简而言之:只有IManufacturerRepository
的实现应该知道IManufacturer
的实际实现(并且只有IManufacturer
的实现应该知道{{1}的实现) }。