我知道有很多关于这两种模式之间差异的帖子,但有一些东西我找不到。
From what I have been reading, I see that the factory method pattern allows you to define how to create a single concrete product but hiding the implementation from the client as they will see a generic product. My first question is about the abstract factory. Is its role to allow you to create families of concrete objects in (that can depend on what specific factory you use) rather than just a single concrete object? Does the abstract factory only return one very large object or many objects depending on what methods you call?
我最后两个问题是关于一句我在很多地方都见过的引语,我不能完全理解:
两者之间的一个区别是
使用抽象工厂模式,a
类委托的责任
对象实例化到另一个对象
通过合成,而工厂
方法模式使用继承和
类依赖于子类来处理
所需的对象实例化。
我的理解是,工厂方法模式有一个Creator接口,它将使ConcreteCreator负责知道要实例化哪个ConcreteProduct。这就是使用继承来处理对象实例化的意思吗?
现在,关于引用,抽象工厂模式是如何通过组合将对象实例化的责任委托给另一个对象的?这是什么意思?在我看来,抽象工厂模式似乎也使用继承来完成构造过程,但我仍然在学习这些模式。
任何帮助,特别是最后一个问题,将非常感激。
工厂设计模式
generation 1 <- generation 2 <- generation 3
//example
(generation 1) shape <- (generation 2) rectangle, oval <- (generation 3) rectangle impressionism, rectangle surrealism, oval impressionism, oval surrealism
工厂
用例:实例化第2代的一个对象
这是一种创造模式,允许你在一个简单的地方创建第2代。它符合SRP和OCP -所有的更改都在一个类中进行。
enum ShapeType {
RECTANGLE,
OVAL
}
class Shape {}
//Concrete Products
//generation 2
class Rectangle extends Shape {}
class Oval extends Shape {}
//Factory
class Factory {
Shape createShape(ShapeType type) {
switch (type) {
case RECTANGLE:
return new Rectangle();
case OVAL:
return new Oval();
}
}
}
//Creator
class Painter {
private Factory factory;
Painter(Factory factory) {
this.factory = factory;
}
Shape prepareShape(ShapeType type) {
return factory.createShape(type);
}
}
//using
class Main {
void main() {
Painter painter = new Painter(new Factory());
Shape shape1 = painter.prepareShape(ShapeType.RECTANGLE);
Shape shape2 = painter.prepareShape(ShapeType.OVAL);
}
}
工厂方法
用例:实例化第3代的一个对象
有助于与下一代家庭成员合作。每个画家都有自己的风格,印象派、超现实主义……工厂方法使用抽象创造者作为工厂(抽象方法),具体创造者是这种方法的实现
enum ShapeType {
RECTANGLE,
OVAL
}
class Shape {}
//Concrete Products
//generation 2
class Rectangle extends Shape {}
class Oval extends Shape {}
//generation 3
class RectangleImpressionism extends Rectangle {}
class OvalImpressionism extends Oval {}
class RectangleSurrealism extends Rectangle {}
class OvalSurrealism extends Oval {}
//Creator
abstract class Painter {
Shape prepareShape(ShapeType type) {
return createShape(type);
}
//Factory method
abstract Shape createShape(ShapeType type);
}
//Concrete Creators
class PainterImpressionism {
@override
Shape createShape(ShapeType type) {
switch (type) {
case RECTANGLE:
return new RectangleImpressionism();
case OVAL:
return new OvalImpressionism();
}
}
}
class PainterSurrealism {
@override
Shape createShape(ShapeType type) {
switch (type) {
case RECTANGLE:
return new RectangleSurrealism();
case OVAL:
return new OvalSurrealism();
}
}
}
//using
class Main {
void main() {
Painter painterImpressionism = new PainterImpressionism();
Shape shape1 = painterImpressionism.prepareShape(ShapeType.RECTANGLE);
Painter painterSurrealism = new PainterSurrealism();
Shape shape2 = painterSurrealism.prepareShape(ShapeType.RECTANGLE);
}
}
抽象工厂
用例:实例化第3代的所有对象
工厂是抽象工厂和具象工厂的一部分
//Concrete Products
//generation 2
class Rectangle extends Shape {}
class Oval extends Shape {}
//generation 3
class RectangleImpressionism extends Rectangle {}
class OvalImpressionism extends Oval {}
class RectangleSurrealism extends Rectangle {}
class OvalSurrealism extends Oval {}
//Abstract Factory
interface Factory {
Rectangle createRectangle();
Oval createOval();
}
//Concrete Factories
class ImpressionismFactory implements Factory {
@Override
public Rectangle createRectangle() {
return new RectangleImpressionism();
}
@Override
public Oval createOval() {
return new OvalImpressionism();
}
}
class SurrealismFactory implements Factory {
@Override
public Rectangle createRectangle() {
return new RectangleSurrealism();
}
@Override
public Oval createOval() {
return new OvalSurrealism();
}
}
//Creator
class Painter {
Rectangle rectangle;
Oval oval;
Painter(Factory factory) {
rectangle = factory.createRectangle();
rectangle.resize();
oval = factory.createOval();
oval.resize();
}
}
//using
class Main {
void main() {
Painter painter1 = new Painter(new ImpressionismFactory());
Shape shape1 = painter1.rectangle;
Shape shape2 = painter1.oval;
Painter painter2 = new Painter(new ImpressionismFactory());
Shape shape3 = painter2.rectangle;
Shape shape4 = painter1.oval;
}
}
为了使它非常简单,界面最小,请关注“//1”:
class FactoryProgram
{
static void Main()
{
object myType = Program.MyFactory("byte");
Console.WriteLine(myType.GetType().Name);
myType = Program.MyFactory("float"); //3
Console.WriteLine(myType.GetType().Name);
Console.ReadKey();
}
static object MyFactory(string typeName)
{
object desiredType = null; //1
switch (typeName)
{
case "byte": desiredType = new System.Byte(); break; //2
case "long": desiredType = new System.Int64(); break;
case "float": desiredType = new System.Single(); break;
default: throw new System.NotImplementedException();
}
return desiredType;
}
}
这里的要点:1。Factory和AbstractFactory机制必须使用继承(System。对象->字节,浮点…所以如果你在程序中有继承,那么根据设计2,工厂(抽象工厂很可能不在那里)已经在那里了。Creator (MyFactory)知道具体类型,因此返回具体类型对象给调用者(Main);在抽象工厂中,返回类型是一个接口。
interface IVehicle { string VehicleName { get; set; } }
interface IVehicleFactory
{
IVehicle CreateSingleVehicle(string vehicleType);
}
class HondaFactory : IVehicleFactory
{
public IVehicle CreateSingleVehicle(string vehicleType)
{
switch (vehicleType)
{
case "Sports": return new SportsBike();
case "Regular":return new RegularBike();
default: throw new ApplicationException(string.Format("Vehicle '{0}' cannot be created", vehicleType));
}
}
}
class HeroFactory : IVehicleFactory
{
public IVehicle CreateSingleVehicle(string vehicleType)
{
switch (vehicleType)
{
case "Sports": return new SportsBike();
case "Scooty": return new Scooty();
case "DarkHorse":return new DarkHorseBike();
default: throw new ApplicationException(string.Format("Vehicle '{0}' cannot be created", vehicleType));
}
}
}
class RegularBike : IVehicle { public string VehicleName { get { return "Regular Bike- Name"; } set { VehicleName = value; } } }
class SportsBike : IVehicle { public string VehicleName { get { return "Sports Bike- Name"; } set { VehicleName = value; } } }
class RegularScooter : IVehicle { public string VehicleName { get { return "Regular Scooter- Name"; } set { VehicleName = value; } } }
class Scooty : IVehicle { public string VehicleName { get { return "Scooty- Name"; } set { VehicleName = value; } } }
class DarkHorseBike : IVehicle { public string VehicleName { get { return "DarkHorse Bike- Name"; } set { VehicleName = value; } } }
class Program
{
static void Main(string[] args)
{
IVehicleFactory honda = new HondaFactory(); //1
RegularBike hondaRegularBike = (RegularBike)honda.CreateSingleVehicle("Regular"); //2
SportsBike hondaSportsBike = (SportsBike)honda.CreateSingleVehicle("Sports");
Console.WriteLine("******* Honda **********"+hondaRegularBike.VehicleName+ hondaSportsBike.VehicleName);
IVehicleFactory hero = new HeroFactory();
DarkHorseBike heroDarkHorseBike = (DarkHorseBike)hero.CreateSingleVehicle("DarkHorse");
SportsBike heroSportsBike = (SportsBike)hero.CreateSingleVehicle("Sports");
Scooty heroScooty = (Scooty)hero.CreateSingleVehicle("Scooty");
Console.WriteLine("******* Hero **********"+heroDarkHorseBike.VehicleName + heroScooty.VehicleName+ heroSportsBike.VehicleName);
Console.ReadKey();
}
}
Important points: 1. Requirement: Honda would create "Regular", "Sports" but Hero would create "DarkHorse", "Sports" and "Scooty". 2. why two interfaces? One for manufacturer type(IVehicleFactory) and another for product factory(IVehicle); other way to understand 2 interfaces is abstract factory is all about creating related objects 2. The catch is the IVehicleFactory's children returning and IVehicle(instead of concrete in factory); so I get parent variable(IVehicle); then I create actual concrete type by calling CreateSingleVehicle and then casting parent object to actual child object. What would happen if I do RegularBike heroRegularBike = (RegularBike)hero.CreateSingleVehicle("Regular");; you will get ApplicationException and that's why we need generic abstract factory which I would explain if required. Hope it helps from beginner to intermediate audience.
抽象工厂创建了一个基类,其抽象方法定义了应该创建的对象的方法。派生基类的每个工厂类都可以创建每种对象类型的自己的实现。
工厂方法只是一个用于在类中创建对象的简单方法。它通常添加在聚合根中(Order类有一个名为CreateOrderLine的方法)
抽象工厂
在下面的示例中,我们设计了一个接口,这样我们就可以将队列创建与消息传递系统分离,因此可以为不同的队列系统创建实现,而不必更改代码库。
interface IMessageQueueFactory
{
IMessageQueue CreateOutboundQueue(string name);
IMessageQueue CreateReplyQueue(string name);
}
public class AzureServiceBusQueueFactory : IMessageQueueFactory
{
IMessageQueue CreateOutboundQueue(string name)
{
//init queue
return new AzureMessageQueue(/*....*/);
}
IMessageQueue CreateReplyQueue(string name)
{
//init response queue
return new AzureResponseMessageQueue(/*....*/);
}
}
public class MsmqFactory : IMessageQueueFactory
{
IMessageQueue CreateOutboundQueue(string name)
{
//init queue
return new MsmqMessageQueue(/*....*/);
}
IMessageQueue CreateReplyQueue(string name)
{
//init response queue
return new MsmqResponseMessageQueue(/*....*/);
}
}
工厂方法
HTTP服务器的问题在于,我们总是需要为每个请求提供响应。
public interface IHttpRequest
{
// .. all other methods ..
IHttpResponse CreateResponse(int httpStatusCode);
}
如果没有工厂方法,HTTP服务器用户(即程序员)将被迫使用特定于实现的类,这就违背了IHttpRequest接口的目的。
因此,我们引入工厂方法,以便响应类的创建也被抽象出来。
总结
区别在于,包含工厂方法的类的预期目的不是创建对象,而抽象工厂应该只用于创建对象。
使用工厂方法时应该小心,因为在创建对象时很容易破坏LSP(里斯科夫替换原则)。
为了便于理解,考虑这个例子。
电信公司提供什么?例如宽带,电话线和移动电话,你被要求创建一个应用程序,向他们的客户提供他们的产品。
一般来说,你在这里要做的是,通过你的工厂方法创建产品,即宽带,电话线和手机,在那里你知道你为这些产品拥有什么属性,这是非常简单的。
现在,该公司想要为他们的客户提供他们的产品捆绑,即宽带、电话线和移动设备,而抽象工厂就来了。
换句话说,抽象工厂是由其他工厂组成的,他们负责创造自己的产品,抽象工厂知道如何在自己的责任方面把这些产品放在更有意义的地方。
在这种情况下,BundleFactory是抽象工厂,BroadbandFactory, PhonelineFactory和MobileFactory是工厂。为了进一步简化,这些工厂将使用工厂方法初始化各个产品。
运行下面的代码示例:
public class BroadbandFactory : IFactory {
public static Broadband CreateStandardInstance() {
// broadband product creation logic goes here
}
}
public class PhonelineFactory : IFactory {
public static Phoneline CreateStandardInstance() {
// phoneline product creation logic goes here
}
}
public class MobileFactory : IFactory {
public static Mobile CreateStandardInstance() {
// mobile product creation logic goes here
}
}
public class BundleFactory : IAbstractFactory {
public static Bundle CreateBundle() {
broadband = BroadbandFactory.CreateStandardInstance();
phoneline = PhonelineFactory.CreateStandardInstance();
mobile = MobileFactory.CreateStandardInstance();
applySomeDiscountOrWhatever(broadband, phoneline, mobile);
}
private static void applySomeDiscountOrWhatever(Broadband bb, Phoneline pl, Mobile m) {
// some logic here
// maybe manange some variables and invoke some other methods/services/etc.
}
}
希望这能有所帮助。