工厂模式
工厂模式作用
在工厂模式中,在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
需要一辆汽车,可以直接从工厂里面提货,而不用去管这辆汽车是怎么做出来的,以及这个汽车里面的具体实现。
工厂模式可以分为三类:
- 简单工厂模式(Simple Factory)
- 工厂方法模式(Factory Method)
- 抽象工厂模式(Abstract Factory)
简单工厂其实不是一个标准的的设计模式。简单工厂模式可以看为工厂方法模式的一种特例。
优点:
- 一个调用者想创建一个对象,只要知道其名称就可以了。
- 屏蔽产品的具体实现,调用者只关心产品的接口。
简单工厂模式
- 创建一个抽象类产品
Shape接口和实现Shape接口的实体类(具体产品)。 - 定义工厂类
ShapeFactory。 - Client使用
ShapeFactory来获取Shape对象。它将向ShapeFactory传递信息(CIRCLE、RECTANGLE、SQUARE),以便获取它所需对象的类型。
简单工厂模式实例
创建接口
package creational.simple_factory_method;
public interface Shape {
void draw();
}
创建实现接口的实体类
Rectangle.java
package creational.simple_factory_method;
public class Rectangle implements Shape{
@Override
public void draw() {
System.out.println("Inside Rectangle::draw() method.");
}
}
Square.java
package creational.simple_factory_method;
public class Square implements Shape{
@Override
public void draw() {
System.out.println("Inside Square::draw() method.");
}
}
创建工厂
使用了反射:
package creational.simple_factory_method;
public class ShapeFactory {
/**
* 注意,这里需要是static
*/
public static Shape getShape(String shapeType) {
Shape shape = null;
try {
shape = (Shape) Class.forName(shapeType).newInstance();
} catch (IllegalAccessException | InstantiationException | ClassNotFoundException e) {
e.printStackTrace();
}
return shape;
}
}
客户调用
package creational.simple_factory_method;
public class Client {
public static void main(String[] args) {
Shape shape = ShapeFactory.getShape("creational.simple_factory_method.Square");
if (shape != null) {
shape.draw(); // Inside Square::draw() method.
}
}
}
工厂方法模式
工厂方法模式实例
创建抽象产品和具体产品
创建抽象产品:
package creational.factory_method.product;
/**
* 通用产品接口:产品接口中将声明所有具体产品都必须实现的操作。
* @author chenzufeng
*/
public interface Animal {
void show();
}
具体产品:
package creational.factory_method.product;
public class Horse implements Animal {
@Override
public void show() {
System.out.println("展示刚出生的小马!");
}
}
package creational.factory_method.product;
public class Cattle implements Animal{
@Override
public void show() {
System.out.println("展示刚出生的小牛!");
}
}
创建抽象工厂和具体工厂
创建抽象工厂:
package creational.factory_method.factory;
import creational.factory_method.product.Animal;
/**
* 基础创建者
* [创建者类]声明的工厂方法必须返回一个产品类的对象。[创建者的子类]通常会提供该方法的实现。
* Base factory class.
* Note that "factory" is merely a role for the class.
* It should have some core business logic which needs different products to be created.
* @author chenzufeng
*/
public abstract class AnimalFactory {
/**
* 具体创建者需要提供一些工厂方法的默认实现
* Subclasses will override this method in order to create specific button objects.
* @return Animal
*/
public abstract Animal createAnimal();
/**
* Creator's primary responsibility isn't creating products.
* It usually contains some [core business logic] that relies on product objects returned by the factory method.
* Subclasses can indirectly change that business logic by [overriding the factory method] and
* returning a different type of product from it.
*/
public void renderAnimal() {
Animal animal = createAnimal();
animal.show();
}
}
创建具体工厂:
package creational.factory_method.factory;
import creational.factory_method.product.Animal;
import creational.factory_method.product.Horse;
public class HorseFactory extends AnimalFactory{
@Override
public Animal createAnimal() {
return new Horse();
}
}
package creational.factory_method.factory;
import creational.factory_method.product.Animal;
import creational.factory_method.product.Cattle;
public class CattleFactory extends AnimalFactory{
@Override
public Animal createAnimal() {
return new Cattle();
}
}
客户端
package creational.factory_method;
import creational.factory_method.factory.AnimalFactory;
import creational.factory_method.factory.CattleFactory;
import creational.factory_method.factory.HorseFactory;
public class Client {
private static AnimalFactory animalFactory;
public static void main(String[] args) {
configure("Horse");
runBusinessLogic();
}
/**
* The concrete factory is usually chosen depending on configuration.
*/
static void configure(String animalType) {
if (animalType.equalsIgnoreCase("Horse")) {
animalFactory = new HorseFactory();
} else if (animalType.equalsIgnoreCase("Cattle")) {
animalFactory = new CattleFactory();
}
}
/**
* All of the client code should work with factories and products through abstract interfaces.
* This way it does not care which factory it works with and what kind of product it returns.
*/
static void runBusinessLogic() {
animalFactory.renderAnimal();
}
}
工厂方法模式优缺点
优缺点
工厂方法模式的主要优点有:
- 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程;
- 在系统增加新的产品时只需要添加
具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则。 - 解耦合
- 耦合:代码间的强关联,一方的改变会影响到另一方,不利于代码维护(把接口的实现类,硬编码在程序中)
其缺点是
- 每增加一个产品就要增加一个
具体产品类和一个对应的具体工厂类,这增加了系统的复杂度。 - 抽象产品只能生产产品的一种类型。
抽象工厂模式
工厂方法模式中考虑的是一类产品的生产,如畜牧场只养动物、电视机厂只生产电视机。但是在现实生活中许多工厂是综合型的工厂,能生产多等级(种类) 的产品,如农场里既养动物又种植物,电器厂既生产电视机又生产洗衣机或空调等。
抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级(种类)的产品,而抽象工厂模式可生产多个等级(种类)的产品。
抽象工厂模式结构
抽象工厂模式实例
抽象产品与具体产品
抽象产品:椅子和沙发
package creational.abstract_factory_method.products.chair;
/**
* 系列产品中的特定产品必须有一个基础接口。所有产品变体都必须实现这个接口。
* Abstract Factory assumes that you have several families of products,
* structured into separate class hierarchies (Chair/Sofa).
* All products of the same family have the common interface.
*
* This is the common interface for chairs family.
* @author chenzufeng
*/
public interface Chair {
void sitOn();
}
package creational.abstract_factory_method.products.sofa;
/**
* This is the common interface for sofa family.
* @author chenzufeng
*/
public interface Sofa {
void sitOn();
}
具体产品:维多利亚和现代风格的椅子和沙发
维多利亚风格的椅子:
package creational.abstract_factory_method.products.chair;
/**
* 具体产品由相应的具体工厂创建。
* All products families have the same varieties (Victorian/Modern).
* This is a Victorian variant of a chair. 维多利亚风格的椅子
* @author chenzufeng
*/
public class VictorianChair implements Chair {
@Override
public void sitOn() {
System.out.println("坐在维多利亚风格的椅子上!");
}
}
现代风格的椅子:
package creational.abstract_factory_method.products.chair;
/**
* 具体产品由相应的具体工厂创建。
* All products families have the same varieties (Victorian/Modern).
* This is a Modern variant of a chair. 现代风格的椅子
* @author chenzufeng
*/
public class ModernChair implements Chair {
@Override
public void sitOn() {
System.out.println("坐在现代风格的椅子上!");
}
}
维多利亚风格的沙发:
package creational.abstract_factory_method.products.sofa;
/**
* 具体产品由相应的具体工厂创建。
* All products families have the same varieties (Victorian/Modern).
* This is a Victorian variant of a sofa. 维多利亚风格的沙发
* @author chenzufeng
*/
public class VictorianSofa implements Sofa {
@Override
public void sitOn() {
System.out.println("坐在维多利亚风格的沙发上!");
}
}
现代风格的沙发:
package creational.abstract_factory_method.products.sofa;
/**
* 具体产品由相应的具体工厂创建。
* All products families have the same varieties (Victorian/Modern).
* This is a Modern variant of a chair. 现代风格的沙发
* @author chenzufeng
*/
public class ModernSofa implements Sofa {
@Override
public void sitOn() {
System.out.println("坐在现代风格的沙发上!");
}
}
抽象工厂与具体工厂
抽象工厂
package creational.abstract_factory_method.factories;
import creational.abstract_factory_method.products.chair.Chair;
import creational.abstract_factory_method.products.sofa.Sofa;
/**
* 抽象工厂接口声明了一组能返回不同抽象产品的方法。
* 这些产品属于[同一个系列]且在高层主题或概念上具有相关性。
* 同系列的产品通常能相互搭配使用:【现代风格的沙发和椅子】。
* 系列产品可有多个变体(现代风格和维多利亚风格),但不同变体的产品不能搭配使用。
* Abstract factory knows about all (abstract) product types.
* @author chenzufeng
*/
public interface FurnitureFactory {
/**
* 创建不同风格的椅子
* @return Chair
*/
Chair createChair();
/**
* 创建不同风格的沙发
* @return Sofa
*/
Sofa createSofa();
}
具体工厂
维多利亚家具厂:
package creational.abstract_factory_method.factories;
import creational.abstract_factory_method.products.chair.Chair;
import creational.abstract_factory_method.products.chair.VictorianChair;
import creational.abstract_factory_method.products.sofa.Sofa;
import creational.abstract_factory_method.products.sofa.VictorianSofa;
/**
* 维多利亚家具厂:生产维多利亚风格的椅子和沙发
* @author chenzufeng
*/
public class VictorianFurnitureFactory implements FurnitureFactory {
@Override
public Chair createChair() {
return new VictorianChair();
}
@Override
public Sofa createSofa() {
return new VictorianSofa();
}
}
现代风格家具厂:
package creational.abstract_factory_method.factories;
import creational.abstract_factory_method.products.chair.Chair;
import creational.abstract_factory_method.products.chair.ModernChair;
import creational.abstract_factory_method.products.sofa.ModernSofa;
import creational.abstract_factory_method.products.sofa.Sofa;
/**
* 现代风格家具厂:生产现代风格椅子和沙发
* @author chenzufeng
*/
public class ModernFurnitureFactory implements FurnitureFactory {
@Override
public Chair createChair() {
return new ModernChair();
}
@Override
public Sofa createSofa() {
return new ModernSofa();
}
}
客户端
客户端应用:
package creational.abstract_factory_method.app;
import creational.abstract_factory_method.factories.FurnitureFactory;
import creational.abstract_factory_method.products.chair.Chair;
import creational.abstract_factory_method.products.sofa.Sofa;
/**
* 客户端应用代码
* @author chenzufeng
*/
public class Application {
private Chair chair;
private Sofa sofa;
public Application(FurnitureFactory furnitureFactory) {
chair = furnitureFactory.createChair();
sofa = furnitureFactory.createSofa();
}
public void sitOn() {
chair.sitOn();
sofa.sitOn();
}
}
客户挑选统一风格的家具:
package creational.abstract_factory_method.app;
import creational.abstract_factory_method.factories.FurnitureFactory;
import creational.abstract_factory_method.factories.ModernFurnitureFactory;
import creational.abstract_factory_method.factories.VictorianFurnitureFactory;
/**
* 客户使用app挑选统一风格的家具
* @author chenzufeng
*/
public class Client {
public static void main(String[] args) {
Application application = configure("Modern");
application.sitOn();
}
private static Application configure(String styleType) {
Application application;
FurnitureFactory furnitureFactory;
if (styleType.equalsIgnoreCase("Modern")) {
furnitureFactory = new ModernFurnitureFactory();
} else if (styleType.equalsIgnoreCase("Victorian")) {
furnitureFactory = new VictorianFurnitureFactory();
} else {
furnitureFactory = null;
}
application = new Application(furnitureFactory);
return application;
}
}
输出结果:
坐在现代风格的椅子上!
坐在现代风格的沙发上!

浙公网安备 33010602011771号