简单工厂模式
定义
定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。
创建实例的方法通常是静态方法
举例
假设有个一个水果农场(工厂),生成多种水果(产品),用户需要购买水果时,只需要告诉农场需要什么水果,农场就会返回需要的水果,而无需一一寻找所需要的水果,这一步农场帮我们完成了
结构
Product
(抽象产品角色):它是工厂类所创建的所有对象的父类,封装了各种产品对象的公共方法,它的引入将提高系统的灵活性,使得在工厂类中只需定义一个通用的工厂ConcreteProduct
(具体产品角色):它是简单工厂模式的创建目标,所有被创建的对象都充当这个角色的某个具体类的实例。每一个具体产品角色都继承了抽象产品角色,需要实现在抽象产品中声明的抽象方法。Factory
(工厂角色):工厂角色即工厂类,它是简单工厂模式的核心,负责实现创建所有产品实例的内部逻辑;工厂类可以被外界直接调用,创建所需的产品对象,返回所需的产品对象
实现
abstract class Product
{
public void MethodSame()
{
//公共方法的实现
}
//声明抽象方法
public abstract void MethodDoff();
}
class ConcretProductA : Product
{
public override void MethodDoff()
{
//业务方法的实现
}
}
class ConcretProductB : Product
{
public override void MethodDoff()
{
//业务方法的实现
}
}
class Factory
{
//静态工厂方法
public static Product GetProduct(string arg)
{
Product product = null;
switch(arg)
{
case "A":
product = new ConcretProductA();
break;
case "B":
product = new ConcretProductB();
break;
}
return product;
}
}
class Program
{
static void Main(string[] args)
{
Product product;
product = Factory.GetProduct("A");
product.MethodSame();
product.MethodDoff();
}
}
简化
可以将抽象产品类(Product)和工厂类(Factory)合并,将静态工厂方法移到抽象产品类中,可以通过调用产品父类的静态工厂方法,根据不同参数创建不同类型的产品子类对象
优点
- (1)工厂类包含必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的职责,而仅仅“消费"产品,简单工厂模式实现了对象创建和使用的分离。
- (2)客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可,对于一些复杂的类名,通过简单工厂模式可以在一定程度上减少使用者的记忆量。
缺点
- (1)由于工厂类集中了所有产品的创建逻辑,职责过重,一旦不能正常工作,整个系统都要受到影响。
- (2)使用简单工厂模式势必会增加系统中类的个数(引人了新的工厂类),增加了系统的复杂度和理解难度。
- (3)系统扩展困难,一旦添加新产品不得不修改工厂逻辑,在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。
- (4)简单工厂模式由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构。在C#语言中,不能通过类的实例对象来访问静态方法和静态变量,无法在客户端代码中针对工厂父类编程,而在运行时使用工厂子类对象来覆盖父类,因此,工厂类不能得到很好地扩展。
适用华环境
- (1)工厂类负责创建的对象比较少,由于创建的对象较少,不会造成工厂方法中的业务逻辑过于复杂。
- (2)客户端只知道传入工厂类的参数,对于如何创建对象并不关心。
工厂方法模式
工厂方法模式是简单工厂模式的延伸,它继承了简单工厂模式的优点,同时还弥补了简单工厂模式的缺陷,更好地符合开闭原则的要求,在增加新的具体产品对象时不需要对已有系统做任何修改。
定义
定义一个用于创建对象的接口,但是让子类决定将哪一个类实例化。
工厂方法模式让一个类的实例化延迟到其子类。
在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。
结构
- (1)Product(抽象产品):它是定义产品的抽象类﹐是工厂方法模式所创建对象的超类型,也就是产品对象的公共父类。
- (2)ConcreteProductA/B(具体产品):它实现了抽象产品接口,某种类型的具体产品由专门的具体工厂创建,具体工厂和具体产品之间一一对应。
- (3)Factory(抽象工厂):抽象工厂接口,声明了工厂方法,用于返回一个产品。抽象工厂是工厂方法模式的核心,所有创建对象的工厂类都必须实现该接口。
- (4)ConcreteFactory(具体工厂):抽象工厂接口,实现了在抽象工厂中声明的工厂方法,由客户端调用,返回一个具体产品类的实例。
实现
abstract class Product
{
public void MethodSame()
{
//公共方法的实现
}
//声明抽象方法
public abstract void MethodDoff();
}
//抽象工厂
interface IFactory
{
Product FactoryMethod();
}
//工厂A类
class ConcretFactoryA : IFactory
{
public Product FactoryMethod()
{
return new ConcretProductA();
}
}
//实现类A
class ConcretProductA : Product
{
public override void MethodDoff()
{
//业务方法的实现
}
}
//工厂B类
class ConcretFactoryB : IFactory
{
public Product FactoryMethod()
{
return new ConcretProductB();
}
}
//实现类B
class ConcretProductB : Product
{
public override void MethodDoff()
{
//业务方法的实现
}
}
class Program
{
static void Main(string[] args)
{
IFactory factory;
factory = new ConcretFactoryA();
Product product;
product = factory.FactoryMethod();
}
}
优点
- (1)在工厂方法模式中,用户无需关心实现细节,只需要关系所对应的工厂即可
- (2)多态性是工厂方法模式的关键。它能够让工厂自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部。工厂方法模式之所以被称为多态工厂模式,就是因为所有的具体工厂类都具有同一抽象父类。
- (3)加入新产品类时,无需修改抽象工厂和抽象工厂接口,而只要添加一个具体工厂和具体产品即可,这样,系统的可扩展性也就变得非常好,完全符合开闭原则。
缺点
- (1)添加新产品类时,需要添加具体的工厂类,增加系统复杂度,带来额外的开销
- (2)由于考虑到系统的可扩展性,需要引人抽象层,增加理解难度
适用环境
- (1)客户端不知道它所需要的对象的类
- (2)抽象工厂类通过其子类来指定创建哪个对象。
抽象工厂模式
与工厂方法模式不同,每个工厂类不只是生产一种,而是生产多个
定义
提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。
结构
- (1)AbstractFactory(抽象工厂):它声明了一组用于创建一族产品的方法,每一个方法对应一种产品。
- (2)ConcreteFactory(具体工厂):它实现了在抽象工厂中声明的创建产品的方法,生成一组具体产品,这些产品构成了一个产品族,每一个产品都位于某个产品等级结构中。
- (3)AbstractProduct(抽象产品):它为每种产品声明接口,在抽象产品中声明了产品所具有的业务方法。
- (4)ConcreteProduct(具体产品):它定义具体工厂生产的具体产品对象,实现抽象产品接口中声明的业务方法。
实现
//产品A属性
class ProductA
{
private int _id;
public int ID
{
get { return _id; }
set { _id = value; }
}
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
}
//产品B属性
class ProductB
{
private int _id;
public int ID
{
get { return _id; }
set { _id = value; }
}
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
}
//抽象工厂
interface IAbstractFactory
{
IAbstractProudctA CreateProductA();
IAbstractProudctB CreateProductB();
}
//具体工厂A
class ConcreteFactoryA : IAbstractFactory
{
public IAbstractProudctA CreateProductA()
{
return new ConcreteProductA();
}
public IAbstractProudctB CreateProductB()
{
return new ConcreteProductB();
}
}
//具体工厂B
class ConcreteFactoryB : IAbstractFactory
{
public IAbstractProudctA CreateProductA()
{
return new ConcreteProductA();
}
public IAbstractProudctB CreateProductB()
{
return new ConcreteProductB();
}
}
//抽象产品A
interface IAbstractProudctA
{
void ConcreteProductA1(ProductA user);
ProductA ConcreteProductA2(int id);
}
//抽象产品B
interface IAbstractProudctB
{
void ConcreteProductB1(ProductB user);
ProductB ConcreteProductB2(int id);
}
//具体产品A
class ConcreteProductA : IAbstractProudctA
{
public ProductA ConcreteProductA2(int id)
{
//产品具体实现
Console.WriteLine("在ConcreteProductA中获取ProductA表记录");
return null;
}
public void ConcreteProductA1(ProductA user)
{
//产品具体实现
Console.WriteLine("在ConcreteProductA中给ProductA表增加一条记录");
}
}
class ConcreteProductB : IAbstractProudctB
{
public ProductB ConcreteProductB2(int id)
{
//产品具体实现
return null;
}
public void ConcreteProductB1(ProductB user)
{
//产品具体实现
}
}
class Program
{
static void Main(string[] args)
{
ProductA abstractProductA = new ProductA();
ProductB abstractProductB = new ProductB();
IAbstractFactory abstractFactory = new ConcreteFactoryA(); //只需确定实例化哪个
IAbstractProudctA concreteProductA = abstractFactory.CreateProductA();
concreteProductA.ConcreteProductA1(abstractProductA);
concreteProductA.ConcreteProductA2(2);
IAbstractProudctB concreteProductB = abstractFactory.CreateProductB();
concreteProductB.ConcreteProductB1(abstractProductB);
concreteProductB.ConcreteProductB2(2);
}
}
优点
- (1)抽象工厂模式隔离了具体类的生成,使得客户端并不需要知道什么被创建。
- (2)当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。
- (3)抽象工厂模式增加新的产品族很方便,无须修改已有系统,符合开闭原则。
缺点
增加新的产品等级结构麻烦,需要对原有系统进行较大的修改,甚至需要修改抽象层代码,这显然会带来较大的不便,违背了开闭原则。
适用环境
- (1)一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节
- (2)系统中有多于一个的产品族,但每次只使用其中某一产品族,可以通过配置文件等方式使用户能够动态地改变产品族,也可以很方便地增加新的产品族。
- (3)属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来。
- (4)产品等级结构稳定,设计完成之后,不会向系统中增加新的产品等级结构或者删除已有的产品等级结构。