简单工厂
在简单工厂模式中,可以根据参数的不同返回不同类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
简单工厂模式主要包含以下角色:
- 工厂类(Factory):这是简单工厂模式的核心,含有一定的商业逻辑和提供创建对象的方法。
- 抽象产品(Product):简单工厂模式所创建的所有对象的父类,负责描述所有实例所共有的公共接口。
- 具体产品(ConcreteProduct):工厂类所创建的对象,它们都继承自抽象产品,是一组实现了不同功能的类。
在简单工厂模式中,客户端不需要知道它所创建的具体产品类的类名,只需要知道相应的参数即可,对于客户端来说,简单工厂模式解耦了客户端与具体产品类之间的关系。
public interface Mouse {
void sayHi();
}
public class DellMouse implements Mouse{
@Override
public void sayHi() {
System.out.println("DellMouse");
}
}
public class HpMouse implements Mouse{
@Override
public void sayHi() {
System.out.println("HpMouse");
}
}
public class MouseFactory {
Mouse create(String type) {
switch (type) {
case "dell":
return new DellMouse();
case "hp":
return new HpMouse();
default:
throw new IllegalStateException();
}
}
}
public static void main(String[] args) {
MouseFactory mouseFactory = new MouseFactory();
Mouse dell = mouseFactory.create("dell");
dell.sayHi();
}
public class DellMouseFactory implements MouseFactory{
@Override
public Mouse createMouse() {
return new DellMouse();
}
}
public class HpMouseFactory implements MouseFactory{
@Override
public Mouse createMouse() {
return new HpMouse();
}
}
简单工厂模式虽然简单方便,但存在一些明显的缺点,主要包括:
-
工厂类的职责过重: 简单工厂模式的工厂类负责实例化所有产品,这就使得工厂类的职责相对过重,容易变得庞大复杂。一旦需要增加新的产品或者修改现有产品的创建逻辑,都需要直接修改工厂类。
-
违反开闭原则: 简单工厂模式由于在工厂类中固定了所有可能被创建的产品种类,对于新的产品类型,需要修改工厂类的判断逻辑,这就违背了“开闭原则”(一个软件实体应当对扩展开放(添加新的功能), 对修改关闭)。
-
系统扩展困难: 当产品种类非常多或者产品层次复杂时,工厂类的逻辑将变得非常复杂,增加系统的修改和维护难度。
-
不易于维护和测试: 当产品实例化逻辑在一个类中集中可能会导致模块代码相互影响,出错后不容易维护和排查错误。
工厂方法模式
工厂方法模式(Factory Method Pattern)是一种创建型设计模式,它提供了一种方式,将创建对象的职责从一个主要的类(如简单工厂的工厂类)转移到专门的函数(即工厂方法)上,这些函数通常存放在子类中。
工厂方法模式主要包含以下角色:
-
抽象工厂(Creator):这是工厂方法模式的核心,提供一个提供产品对象的工厂方法,这个工厂方法通常是抽象的,需要由具体工厂来实现。
-
具体工厂(ConcreteCreator):是抽象工厂的子类,实现了抽象工厂中的工厂方法,这个方法用来创建具体产品。
-
抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能。
-
具体产品(ConcreteProduct):抽象产品的实现类。
public interface Mouse {
void sayHi();
}
public class DellMouse implements Mouse{
@Override
public void sayHi() {
System.out.println("DellMouse");
}
}
public class HpMouse implements Mouse{
@Override
public void sayHi() {
System.out.println("HpMouse");
}
}
public interface MouseFactory {
Mouse createMouse();
}
public class DellMouseFactory implements MouseFactory{
@Override
public Mouse createMouse() {
return new DellMouse();
}
}
public class HpMouseFactory implements MouseFactory{
@Override
public Mouse createMouse() {
return new HpMouse();
}
}
public static void main(String[] args) {
Mouse dellMouse = new DellMouseFactory().createMouse();
dellMouse.sayHi();
}
工厂方法模式的优点:
-
符合开闭原则:当你需要引入新的产品类时,你不需要修改任何现有的代码。可以新增具体工厂类及其所对应的产品类,满足了开闭原则。
-
避免紧密耦合:工厂方法分离了具体类的实例化,使得客户端不需要依赖于具体的类,而只关注与产品接口和抽象类。这大大降低了客户端与产品类之间的耦合度。
-
提高代码的可维护性和可复用性:各产品可独立于工厂进行变动,无需修改工厂类代码,只要求引入新的工厂类即可,代码具有较好的可扩展性和可维护性。
-
有利于产品的一致性:当一个工厂负责生产某个等级结构的所有产品时,可以确保这些产品是相互兼容的,相比简单工厂更有利于生产复杂的产品。
工厂方法模式的缺点:
-
类的数量增多:对于每一个产品都需要创建一个对应的具体工厂类,使得系统中类的数量大幅增加,加大了系统的复杂度。
-
增加了系统结构和代码的复杂性:引入了许多新的子类,如果子类过多,它们之间的区别仅在于生产的结果不同,代码的复用性较差。
-
需要客户端知道所有的工厂实现类:工厂方法模式要求客户端识别并选择合适的工厂进行对象的创建操作,这无疑将一些选择的责任交给了客户端,可能会给客户端造成一定压力。
抽象工厂模式
抽象工厂模式(Abstract Factory Pattern)是一种创建型设计模式,它允许你生产一系列相关的对象,而无需指定它们具体的类。这个模式通常在客户端代码中对具体类的使用进行了抽象,从而使你可以独立于具体实现类来使用它们的功能。
抽象工厂模式通常涉及以下几个角色:
-
抽象工厂(Abstract Factory):提供一个创建一系列相关或相互依赖对象的接口,而不需要指定它们具体的类。
-
具体工厂(Concrete Factory):实现抽象工厂的操作,产生具体的产品对象。
-
抽象产品(Abstract Product):为一类产品对象声明一个接口。
-
具体产品(Concrete Product):抽象产品的实现;具体工厂创建的目标。
-
客户端(Client):只调用抽象工厂和抽象产品提供的接口,不关心创建的具体产品是哪一个。
抽象工厂模式的一个重要特征是它强调一系列产品(可以是不同的产品族)需要以相同的方式进行创建和使用。客户端通过操作抽象类型来创建和使用创建的对象,从而使得客户端可以独立于具体实现工作。
public interface Mouse {
void sayHi();
}
public class DellMouse implements Mouse{
@Override
public void sayHi() {
System.out.println("DellMouse");
}
}
public class HpMouse implements Mouse{
@Override
public void sayHi() {
System.out.println("HpMouse");
}
}
public interface Mic {
void sayHello();
}
public class DellMic implements Mic{
@Override
public void sayHello() {
System.out.println("DellMic");
}
}
public class HpMic implements Mic{
@Override
public void sayHello() {
System.out.println("HpMic");
}
}
public abstract class AbstractFactory {
public abstract Mouse createMouse(String type);
public abstract Mic createMic(String type);
public static AbstractFactory createFactory(String type) {
if (type.equalsIgnoreCase("dell")) {
return new MouseFactory();
} else if (type.equalsIgnoreCase("hp")) {
return new MicFactory();
} else {
throw new IllegalArgumentException();
}
}
}
public class MouseFactory extends AbstractFactory {
@Override
public Mouse createMouse(String type) {
switch (type) {
case "dell":
return new DellMouse();
case "hp":
return new HpMouse();
default:
throw new IllegalStateException();
}
}
@Override
public Mic createMic(String type) {
return null;
}
}
public class MicFactory extends AbstractFactory{
@Override
public Mouse createMouse(String type) {
return null;
}
@Override
public Mic createMic(String type) {
switch (type) {
case "dell":
return new DellMic();
case "hp":
return new HpMic();
default:
throw new IllegalStateException();
}
}
}
public static void main(String[] args) {
AbstractFactory mouseFactory = AbstractFactory.createFactory("mouse");
Mouse dellMouse = mouseFactory.createMouse("dell");
dellMouse.sayHi();
AbstractFactory micFactory = AbstractFactory.createFactory("mic");
Mic hp = micFactory.createMic("hp");
hp.sayHello();
}
抽象工厂模式的优点如下:
-
强化了模块间的低耦合:客户端无须知道它所使用的对象的具体类型,只需知道对象的接口以及相应工厂的接口即可。
-
增强了程序的可扩展性:当增加一个新的产品族时无需修改原有系统代码,满足了开闭原则。
-
增强了产品或产品族在未来的扩展能力:产品的具体实现同客户端的高层次结构分离,有利于产品功能的扩展和变化。
-
强调了一系列相关的产品对象(产品族)的设计以及使用:通过抽象工厂和具体工厂的配合,一次性创建出一个完整的产品系列。
然而,抽象工厂模式也有其缺点:
-
难以支持新种类的产品:抽象工厂模式提供了一种创建产品家族的方式,一旦需要添加新产品,不仅要定义新的具体产品类,同时还需要扩展抽象工厂及其所有子类,这可能会带来复杂性和代码的维护问题。
-
规模过大时,结构可能会变得复杂:当产品系列非常多时,产品的管理和维护可能会变得复杂和困难。
-
增加了系统的抽象性和理解难度:由于引入了多层抽象层,这可能会增加系统的抽象程度和学习曲线。