C语言学习网

设计模式(创建型)之工厂模式

发表于:2022-08-20 作者:安全数据网编辑
编辑最后更新 2022年08月20日,工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。定义一个用于创建对象的接口,让其子类来决定实例化哪一个类(产品),工厂方法使一个类的创建延迟到其子类中

工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。

定义一个用于创建对象的接口,让其子类来决定实例化哪一个类(产品),工厂方法使一个类的创建延迟到其子类中。

工厂模式分为三种:

1)简单工厂模式(Simple Factory)
2)工厂方法模式(Factory Method)
3)抽象工厂模式(Abstract Factory)

一、简单工厂模式:

简单工厂模式(Simple Factory)看为工厂方法模式(Factory Method)的一种特例,从接来下的实例可以看出。

1、组成:
1) 工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑。在java中它往往由一个具体类实现。
2) 抽象产品角色:它一般是具体产品继承的父类或者实现的接口。在java中由接口或者抽象类来实现。
3) 具体产品角色:工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现。

2、UML类图:

3、相关代码:

JAVA:

Factory .java:

// 工厂类角色

public class Factory {
public static AbstractProduct getAnProduct( String s){
if (s.equalsIgnoreCase("product1")){
return new Product1();
}else if(s.equalsIgnoreCase("product2")){
return new Product2();
}else{
System.out.println("This type product is not exist in the factory!!!");
return null;
}
}
}

AbstractProduct .java:

// 抽象产品角色

public interface AbstractProduct {
public void doSomething();
}

Product1 .java:

// 具体产品角色

public class Product1 implements AbstractProduct {

@Override
public void doSomething() {
// TODO Auto-generated method stub
System.out.println("doSomething for Product1!!!");
}

}

Product2 .java:

// 具体产品角色

public class Product2 implements AbstractProduct {

@Override
public void doSomething() {
// TODO Auto-generated method stub
System.out.println("doSomething for Product2!!!");
}

}

testMain .java:

// 测试类

public class testMain {

/**
* @param args
*/
public static void main(String[] args) {
AbstractProduct p1 = Factory.getAnProduct("product1");
p1.doSomething();
AbstractProduct p2 = Factory.getAnProduct("product2");
p2.doSomething();
AbstractProduct p3 = Factory.getAnProduct("product1");
p3.doSomething();
AbstractProduct p4 = Factory.getAnProduct("product2");
p4.doSomething();

}

}

运行结果:

doSomething for Product1!!!
doSomething for Product2!!!
doSomething for Product1!!!
doSomething for Product2!!!

C++:

//============================================================================
// Name : SimpleFactory.cpp
// Author : Yan chao

// Version :
// Copyright : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include
using namespace std;

// 抽象产品角色

class AbstractProduct{
public:
AbstractProduct(){}
virtual void doSomething() = 0;
virtual ~AbstractProduct(){}
};

// 具体产品角色

class Product1 : public AbstractProduct{
public:
void doSomething(){
cout << "doSomething for Product1!!!" << endl;
}
};

// 具体产品角色

class Product2 : public AbstractProduct{
public:
void doSomething(){
cout << "doSomething for Product2!!!" << endl;
}
};

// 工厂类角色

class SimpleFactory{
public:
static AbstractProduct* getProduct(string s){

if ( s.compare("product1") == 0 ){
cout << "s1:" << s << endl;
return new Product1();
}else if( s.compare("product2") == 0 ){
cout << "s2:" << s << endl;
return new Product2();
}else{
cout << "This type product is not exist in the factory!!!" << endl;
return NULL;
}
}
};

int main() {
SimpleFactory::getProduct("product1")->doSomething();
SimpleFactory::getProduct("product2")->doSomething();
SimpleFactory::getProduct("product2")->doSomething();
return 0;
}

运行结果:

s1:product1
doSomething for Product1!!!
s2:product2
doSomething for Product2!!!
s2:product2
doSomething for Product2!!!

我们从开闭原则对扩展开放,对修改封闭)上来分析下简单工厂模式。当我们想增加了一个产品的时候,只要符合抽象产品的规则,那么只要通知工厂类知道就可以被客户使用了。所以对产品部分来说,它是符合开闭原则的;但是工厂部分好像不太理想,因为每增加一个产品,都要在工厂类中增加相应的业务逻辑或者判断逻辑,这显然是违背开闭原则的。可想而知对于新产品的加入,工厂类是很被动的。对于这样的工厂类,我们称它为全能类或者上帝类。
在实际应用中,很可能产品是一个多层次的树状结构。由于简单工厂模式中只有一个工厂类来对应这些产品,所以这可能会把我们的上帝累坏了,也累坏了我们这些程序员。所以,就有了工厂方法模式!

二、工厂方法模式:

工厂方法模式中,工厂类角色也抽象化了!这样就有多个工厂类来分别对应不同的产品了。

1、组成:

1) 抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java 中它由抽象类或者接口来实现。
2) 具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。
3) 抽象产品角色:它是具体产品继承的父类或者是实现的接口。在 java 中一般有抽象类或者接口来实现。
4) 具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在 java 中由具体的类
来实现。

2、UML类图:

3、代码实现:

JAVA:

AbstractFactory .java:

// 抽象工厂角色

public abstract class AbstractFactory {
abstract AbstractProduct getAnProduct();
}

AbstractProduct.java:

// 抽象产品角色

public interface AbstractProduct {
public void doSomething();
}

Factory1.java:

// 具体工厂角色

public class Factory1 extends AbstractFactory {

@Override
AbstractProduct getAnProduct() {
// TODO Auto-generated method stub
return new Product1();
}

}

Factory2.java:

// 具体工厂角色

public class Factory2 extends AbstractFactory {

@Override
AbstractProduct getAnProduct() {
// TODO Auto-generated method stub
return new Product2();
}

}

Product1.java:

// 具体产品角色

public class Product1 implements AbstractProduct {

public void doSomething() {
// TODO Auto-generated method stub
System.out.println("doSomething for Product1!!!");
}

}

Product2.java:

// 具体产品角色

public class Product2 implements AbstractProduct {

public void doSomething() {
// TODO Auto-generated method stub
System.out.println("doSomething for Product2!!!");
}

}

testMain.java:

// 测试类

public class testMain {

/**
* @param args
*/
public static void main(String[] args) {
Factory1 fc1 = new Factory1();
Factory2 fc2 = new Factory2();
fc1.getAnProduct().doSomething();
fc1.getAnProduct().doSomething();
fc1.getAnProduct().doSomething();
fc2.getAnProduct().doSomething();
fc2.getAnProduct().doSomething();
fc2.getAnProduct().doSomething();
fc2.getAnProduct().doSomething();

}

}

运行结果:

doSomething for Product1!!!
doSomething for Product1!!!
doSomething for Product1!!!
doSomething for Product2!!!
doSomething for Product2!!!
doSomething for Product2!!!
doSomething for Product2!!!

C++:

//============================================================================
// Name : Factory.cpp
// Author : Yan chao
// Version :
// Copyright : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include
using namespace std;

class AbstractProduct{
public:
AbstractProduct(){}
virtual void doSomething() = 0;
virtual ~AbstractProduct(){}
};

class Product1 : public AbstractProduct{
public:
void doSomething(){
cout << "doSomething for Product1!!!" << endl;
}
};

class Product2 : public AbstractProduct{
public:
void doSomething(){
cout << "doSomething for Product2!!!" << endl;
}
};

class AbstractFactory {
public:
virtual AbstractProduct* getProduct()=0;
virtual ~AbstractFactory(){}
};

class Factory1 : public AbstractFactory{
public:
Product1* getProduct(){
return new Product1();
}
};

class Factory2 : public AbstractFactory{
public:
Product2* getProduct(){
return new Product2();
}
};

int main() {
Factory1* f1 = new Factory1();
Factory2* f2 = new Factory2();
f1->getProduct()->doSomething();
f1->getProduct()->doSomething();
f1->getProduct()->doSomething();
f2->getProduct()->doSomething();
f2->getProduct()->doSomething();
f2->getProduct()->doSomething();
return 0;
}

运行结果:

doSomething for Product1!!!
doSomething for Product1!!!
doSomething for Product1!!!
doSomething for Product2!!!
doSomething for Product2!!!
doSomething for Product2!!!

可以看出工厂方法的加入,使得对象的数量成倍增长当产品种类非常多时,会出现大量的与之对应的工厂对象,这不是我们所希望的。因为如果不能避免这种情况,可以考虑使用简单工厂模式与工厂方法模式相结合的方式来减少工厂类:即对于产品树上类似的种类(一般是树的叶子中互为兄弟的)使用简单工厂模式来实现。

简单工厂模式与工厂方法模式真正的避免了代码的改动了?没有。在简单工厂模式中,新产品的加入要修改工厂角色中的判断语句;而在工厂方法模式中,要么将判断逻辑留在抽象工厂角色中,要么在客户程序中将具体工厂角色写死(就象上面的例子一样)。而且产品对象创建条件的改变必然会引起工厂角色的修改。

三、抽象工厂模式:

可以说,抽象工厂模式和工厂方法模式的区别就在于需要创建对象的复杂程度上。而且抽象工厂模式是三个里面最为抽象、最具一般性的。

可以理解为,工厂方法模式中的产品是一维的,而抽象工厂模式中的产品的维度是多维的。(从下联的类图就可以看出来!)

举个具体的例子说明:

上面的类图的产品类的分了两个维度的实例。一个维度是,宝马车和奔驰车;另一个维度是,商务型和运动型。

1、 抽象工厂模式的用意为:给客户端提供一个接口,可以创建多个产品中的产品对象
2、使用抽象工厂模式还要满足一下条件:
1) 系统中有多个产品族,而系统一次只可能消费其中一族产品
2) 同属于同一个产品族的产品以其使用。
3、 组成(和工厂方法类一样):

1) 抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java 中它由抽象类或者接口来实现。
2) 具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。在java 中它由具体的类来实现。
3) 抽象产品角色:它是具体产品继承的父类或者是实现的接口。在 java 中一般有抽象类或者接口来实现。
4) 具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在 java 中由具体的类来实现。

4、UML类图:

5、代码实现:

JAVA:

AbstractFactory.java:

// 抽象工厂角色

public abstract class AbstractFactory {
abstract AbstractProductA getProductA();
abstract AbstractProductB getProductB();
}

AbstractProductA.java:

// 抽象产品角色(A维度)

public interface AbstractProductA {
public void doSomething();
}

AbstractProductB.java:

// 抽象产品角色(B维度)

public interface AbstractProductB {
public void doSomething();
}

Factory1.java:

// 具体工厂角色

public class Factory1 extends AbstractFactory {

@Override
AbstractProductA getProductA() {
// TODO Auto-generated method stub
return new Product1A();
}
AbstractProductB getProductB() {
// TODO Auto-generated method stub
return new Product1B();
}

}

Factory2.java:

// 具体工厂角色
public class Factory2 extends AbstractFactory {

@Override
AbstractProductA getProductA() {
// TODO Auto-generated method stub
return new Product2A();
}

AbstractProductB getProductB() {
// TODO Auto-generated method stub
return new Product2B();
}

}

Product1A.java:

// 具体产品角色(A维度)

public class Product1A implements AbstractProductA {

public void doSomething() {
// TODO Auto-generated method stub
System.out.println("doSomething for Product1A!!!");
}

}

Product2A.java:

// 具体产品角色(A维度)

public class Product2A implements AbstractProductA {

public void doSomething() {
// TODO Auto-generated method stub
System.out.println("doSomething for Product2A!!!");
}

}

Product1B.java:

// 具体产品角色(B维度)

public class Product1B implements AbstractProductB {

public void doSomething() {
// TODO Auto-generated method stub
System.out.println("doSomething for Product1B!!!");
}

}

Product2B.java:

// 具体产品角色(B维度)

public class Product2B implements AbstractProductB {

public void doSomething() {
// TODO Auto-generated method stub
System.out.println("doSomething for Product2B!!!");
}

}

testMain.java:

// 测试类

public class testMain {

/**
* @param args
*/
public static void main(String[] args) {
Factory1 fc1 = new Factory1();
Factory2 fc2 = new Factory2();
fc1.getProductA().doSomething();
fc1.getProductB().doSomething();
fc1.getProductA().doSomething();
fc1.getProductB().doSomething();
fc2.getProductA().doSomething();
fc2.getProductB().doSomething();
fc2.getProductA().doSomething();
fc2.getProductB().doSomething();

}

}

运行结果:

doSomething for Product1A!!!
doSomething for Product1B!!!
doSomething for Product1A!!!
doSomething for Product1B!!!
doSomething for Product2A!!!
doSomething for Product2B!!!
doSomething for Product2A!!!
doSomething for Product2B!!!

0