意图:定义一个用于创建对象的接口,让子类决定实例化哪一个类。 Factory Method使一个类的实例化延迟到其子类。
我将工厂模式分为三个部分:原料、工厂、购买者
一、原料
一般情况下我们的原料属于同种。比如说面积:有圆面积,矩形面积,正方形面积等。这些都属于面积的算法。但是他们具体到某个详细算法时又有所不同,所以我们可以用多个子类继承同一个基类。由于基类不属于某个具体形状。所以它应该定义成抽象类(不能定义对象,只能定义指针和引用,且不能用于函数参数类型和返回值)。纯虚函数只是用来说明,没有具体实现。它的实现应该又每个有具体意义的子类来实现。
基类Shape
#ifndef SHAPE_H
#define SHAPE_H
class Shape
{
public:
Shape();
~Shape();
virtual void getArea()=0;
protected:
private:
};
#endif // SHAPE_H
#include "Shape.h"
Shape::Shape()
{
//ctor
}
Shape::~Shape()
{
//dtor
}
Square子类
#ifndef SQUARE_H
#define SQUARE_H
class Square : public Shape
{
public:
Square();
~Square();
void getArea();
protected:
private:
};
#endif // SQUARE_H
#include <iostream>
#include "Shape.h"
#include "Square.h"
using namespace std;
Square::Square()
{
//ctor
}
Square::~Square()
{
//dtor
}
void Square::getArea(){
cout<<"这是Square类的方法"<<endl;
}
Circle子类
#ifndef CIRCLE_H
#define CIRCLE_H
class Circle : public Shape
{
public:
Circle();
~Circle();
void getArea();
protected:
private:
};
#endif // CIRCLE_H
#include <iostream>
#include "Shape.h"
#include "Circle.h"
using namespace std;
Circle::Circle()
{
//ctor
}
Circle::~Circle()
{
//dtor
}
void Circle::getArea(){
cout<<"这是Circle类方法"<<endl;
}
二、工厂
工厂负责加工这些原料,当购买者需要计算某个面积时,工厂就对原料进行加工产生对应某个面积算法的对象。这个地方用抽象类的好处出来了。由于我们原料的子类都是继承与虚基类。所以我们可以直接返回抽象类的指针,利用C++的多态性(当基类指针进入某个子类的对象,就调用对应子类的函数),将原料子类赋给基类指针。这样我们就可以使用基类类型就可以了,而不需要为了完成赋值类型对应,在购买者函数里定义子类类型。也就是说工厂将原料和购买者分离开来。添加、修改原料不会影响购买者,购买者只需要告诉工厂需要购买何种子类就行,而不需要关注具体子类的实现。
factory类
#ifndef SHAPEFACTORY_H
#define SHAPEFACTORY_H
#include <string>
using namespace std;
class ShapeFactory
{
public:
ShapeFactory();
~ShapeFactory();
Shape* getShape(string);
protected:
private:
};
#endif // SHAPEFACTORY_H
#include <string>
#include "Shape.h"
#include "Square.h"
#include "Circle.h"
#include "ShapeFactory.h"
using namespace std;
ShapeFactory::ShapeFactory()
{
//ctor
}
ShapeFactory::~ShapeFactory()
{
//dtor
}
Shape* ShapeFactory::getShape(string type){
if(type == "CIRCLE"){
return new Circle();
}else if(type == "SQUARE"){
return new Square();
}
return NULL;
}
三、购买者
购买者只需要告诉工厂需要何种类就行,不用关注子类实现。如果我们使用字符串完成子类类型对应,实现逻辑上的对应。那么即使原料类名的更改也不会影响到购买者的调用,只需要对负责产出子类的工厂进行修改。而这种修改很容易就可以实现,因为所有的子类都归工厂管理,集中于工厂类中。不需要到购买者中逐一查找在何处有子类对象。
#include "Shape.h"
#include "ShapeFactory.h"
int main(){
ShapeFactory *factory = new ShapeFactory();
Shape* circle = factory->getShape("CIRCLE");
circle->getArea();
Shape* square = factory->getShape("SQUARE");
square->getArea();
return 0;
}
四、java代码
java代码使用interface和implements实现。
package factory;
public class Circle implements Shape {
public void getArea(){
System.out.println("这是获取circle面积的方法");
}
}
package factory;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
ShapeFactory factory = new ShapeFactory();
Shape circle = factory.getShape("CIRCLE");
circle.getArea();
Shape square = factory.getShape("SQUARE");
square.getArea();
}
}
package factory;
public interface Shape {
void getArea();
}
package factory;
public class ShapeFactory {
public Shape getShape(String shapeType){
if(shapeType == null)
return null;
if(shapeType.equalsIgnoreCase("CIRCLE")){
return new Circle();
}else if(shapeType.equalsIgnoreCase("Square")){
return new Square();
}
return null;
}
}
package factory;
public class Square implements Shape {
public void getArea(){
System.out.println("这是获取square面积的方法");
}
}