创建型模式-抽象工厂模式(三)
目录
抽象工厂描述
抽象工厂存在的问题
解决方案
使用场景
优缺点对比
代码
抽象工厂描述
抽象工厂模式是一种创建型设计模式,它能创建一系列相关的对象,而无需指定其具体类。
抽象工厂存在的问题
假设你正在开发一款家具商店模拟器。你的代码中包括一些类,用于表示:
一系列相关产品,例如椅子Chair 、 沙发Sofa和咖啡桌CoffeeTable。
系列产品的不同变体。例如,你可以使用 现代Modern 、 维多利亚Victorian 、装饰风艺术ArtDeco等风格生成 椅子 、 沙发和咖啡桌。
你需要设法单独生成每件家具对象,这样才能确保其风格一致。 如果顾客收到的家具风格不一样,他们可不会开心。
此外,你也不希望在添加新产品或新风格时修改已有代码。家具供应商对于产品目录的更新非常频繁,你不会想在每次更新时都去修改核心代码的。
解决方案
首先,抽象工厂模式建议为系列中的每件产品明确声明接口(例如椅子、沙发或咖啡桌)。然后, 确保所有产品变体都继承这些接口。例如,所有风格的椅子都实现 椅子接口;所有风格的咖啡桌都实现 咖啡桌接口,以此类推。
使用场景
如果代码需要与多个不同系列的相关产品交互, 但是由于无法提前获取相关信息, 或者出于对未来扩展性的考虑, 你不希望代码基于产品的具体类进行构建, 在这种情况下, 你可以使用抽象工厂。
优缺点对比
优点 | 缺点 |
你可以确保同一工厂生成的产品相互匹配 | 由于采用该模式需要向应用中引入众多接口和类, 代码可能会比之前更加复杂 |
你可以避免客户端和具体产品代码的耦合 | |
单一职责原则。 你可以将产品生成代码抽取到同一位置, 使得代码易于维护 | |
开闭原则。 向应用程序中引入新产品变体时, 你无需修改客户端代码 |
图示表达
这个记忆方法,先分2个模块,抽象产品和抽象工厂模块,然后再根据有多少个抽象产品再次进行分类,而抽象工厂也随着抽象产品的增加而增加。
代码
1.建立一个控制台程序,代码文件总览。可见上面说的缺点,就体现出来了,写了很多的子类,如果分不清结构,将是灾难性的代码。和工厂方法模式一样。
2.抽象产品,AbstractProductA
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp3
{
public abstract class AbstractProductA //抽象产品A类
{
}
}
3.抽象产品,AbstractProductB
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp3
{
public abstract class AbstractProductB //抽象产品B类
{
abstract public void Interact(AbstractProductA a); //抽象方法
}
}
4.具体产品,ProductA1
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp3
{
public class ProductA1 : AbstractProductA //具体产品A1,继承抽象产品A
{
}
}
5.具体产品,ProductA2
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp3
{
public class ProductA2 : AbstractProductA //具体产品A2,继承抽象产品A
{
}
}
6.具体产品,ProductB1
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp3
{
public class ProductB1 : AbstractProductB //具体产品B1,继承抽象产品B
{
public override void Interact(AbstractProductA a) //重写继承抽象B的方法
{
Console.WriteLine(this + " interacts with " + a);
}
}
}
7.具体产品 ,ProductB2
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp3
{
public class ProductB2 : AbstractProductB //具体产品B2,继承抽象产品B
{
public override void Interact(AbstractProductA a) //重写继承抽象B的方法
{
Console.WriteLine(this + " interacts with " + a);
}
}
}
8.抽象工厂,AbstractFactory
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp3
{
public abstract class AbstractFactory //抽象工厂
{
abstract public AbstractProductA CreateProductA(); //定义抽象产品A
abstract public AbstractProductB CreateProductB(); //定义抽象产品B
}
}
9.具体工厂,ConcreteFactory1
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp3
{
public class ConcreteFactory1 : AbstractFactory //具体工厂1,继承抽象工厂
{
public override AbstractProductA CreateProductA() //重写方法
{
return new ProductA1(); //返回产品A1
}
public override AbstractProductB CreateProductB() //重写方法
{
return new ProductB1(); //返回产品B1
}
}
}
10.具体工厂,ConcreteFactory2
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp3
{
class ConcreteFactory2 : AbstractFactory //具体工厂2,继承抽象工厂
{
public override AbstractProductA CreateProductA() //重写方法
{
return new ProductA2(); //返回产品A2
}
public override AbstractProductB CreateProductB() //重写方法
{
return new ProductB2(); //返回产品B2
}
}
}
11.使用
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp3
{
class Program
{
static void Main(string[] args)
{
AbstractFactory factory1 = new ConcreteFactory1();
Environment e1 = new Environment(factory1);
e1.Run();
AbstractFactory factory2 = new ConcreteFactory2();
Environment e2 = new Environment(factory2);
e2.Run();
Console.WriteLine("结束");
}
}
}
12.效果