开闭原则(OCP):一个软件实体如类、模块和函数应该对扩展开放、对修改关闭
一、简单工厂模式
- 一个抽象产品类
- 具体产品类
- 一个工厂
- 优点:简单易于实现,把类的实例化交给工厂,易于解耦
- 缺点:添加具体产品需要修改工厂违反OCP开放封闭原则
interface IM1 {
void computer();
}
class computer implements IM1 {
@Override
public void computer() {
System.out.println("第1个");
}
}
class computers implements IM1 {
@Override
public void computer() {
System.out.println("第2个");
}
}
class Factory {
public static IM1 getInstance(String m) {
IM1 im = null;
if (m.equals("1")) {
im = new computer();
} else if (m.equals("2")) {
im = new computers();
}
return im;
}
}
public class FactoryTest2 {
public void print(IM1 im) {
im.computer();
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String answer = scanner.nextLine();
FactoryTest2 factoryTest2 = new FactoryTest2();
IM1 im= Factory.getInstance(answer);
factoryTest2.print(im);
}
}
二、工厂方法模式
定义一个用来创建对象的接口,也就是工厂,让子类决定实例化哪一个类,让子类决定实例化延迟到子类,工厂方法模式是针对每个产品提供一个工厂类,在客户端中判断使用哪个工厂类去创建对象。
- 一个抽象产品类
- 多个具体产品类
- 一个抽象工厂
- 多个具体工厂
- 每个具体产品对应一个具体工厂
- 优点:降低了代码的耦合度,对象的生成交给子类去完成;实现了(OCP)开放封闭原则,每次添加子产品不需要修改源代码
- 缺点:增加代码量,每个具体产品都需要一个具体工厂
以上俩个工厂的对比
- 对于简单工厂模式而言,创建对象的逻辑判断放在了工厂类中,客户不感知具体的类,但是其违背了开闭原则,如果要增加新的具体类,就必须修改工厂类。
- 对于工厂方法模式而言,是通过扩展来新增具体类的,符合开闭原则,但是在客户端就必须要感知到具体的工厂类,也就是将判断逻辑由简单工厂的工厂类挪到客户端。
- 工厂方法横向扩展很方便,假如该工厂又有新的产品要生产,那么只需要创建相应的工厂类和产品类去实现抽象工厂接口和抽象产品接口即可,而不用去修改原有已经存在的代码。
interface Computer {
void com();
}
class comm1 implements Computer {
@Override
public void com() {
System.out.println("1");
}
}
class comm2 implements Computer {
@Override
public void com() {
System.out.println("2");
}
}
//由工厂来决定实例化的子类
interface ComputerFactory {
Computer get();
}
class com1Factory implements ComputerFactory {
@Override
public Computer get() {
return new comm1();
}
}
class com2Factory implements ComputerFactory {
@Override
public Computer get() {
return new comm2();
}
}
public class FactoryTest3 {
public void print(Computer computer) {
computer.com();
}
public static void main(String[] args) {
FactoryTest3 factoryTest3 = new FactoryTest3();
ComputerFactory factory=new com1Factory();
factoryTest3.print(factory.get());
}
}
三、抽象工厂模式
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
- 多个抽象产品类
- 具体产品类
- 抽象工厂类 - 声明(一组)返回抽象产品的方法
- 具体工厂类 - 生成(一组)具体产品
优点:
- 代码解耦
- 实现多个产品族(相关联产品组成的家族),而工厂方法模式的单个产品,可以满足更多的生产需求
- 很好的满足OCP开放封闭原则
抽象工厂模式中我们可以定义实现不止一个接口,一个工厂也可以生成不止一个产品类 对于复杂对象的生产
相当灵活易扩展
缺点:
- 扩展产品族相当麻烦 而且扩展产品族会违反OCP,因为要修改所有的工厂
- 由于抽象工厂模式是工厂方法模式的扩展 总体的来说很笨重
总结:简单工厂模式最大的优点就是工厂内有具体的逻辑去判断生成什么产品,将类的实例化交给了工厂,这样当我们需要什么产品只需要修改工厂的调用而不需要去修改客户端,对于客户端来说降低了与具体产品的依赖
工厂方法模式是简单工厂的扩展,工厂方法模式把原先简单工厂中的实现那个类的逻辑判断交给了客户端,如果像添加功能只需要修改客户和添加具体的功能,不用去修改之前的类。
抽象工厂模式进一步扩展了工厂方法模式,它把原先的工厂方法模式中只能有一个抽象产品不能添加产品族的缺点克服了,抽象工厂模式不仅仅遵循了OCP原则,而且可以添加更多产品(抽象产品),具体工厂也不仅仅可以生成单一产品,而是生成一组产品,抽象工厂也是声明一组产品,对应扩展更加灵活,但是要是扩展族系就会很笨重。
interface Computer1 {
void computer();
}
class c1 implements Computer1 {
@Override
public void computer() {
System.out.println("c1");
}
}
class c2 implements Computer1 {
@Override
public void computer() {
System.out.println("c2");
}
}
interface CFactory {
void factory();
}
class f1 implements CFactory {
@Override
public void factory() {
System.out.println("f1");
}
}
class f2 implements CFactory {
@Override
public void factory() {
System.out.println("f2");
}
}
interface all {
CFactory c();
Computer1 cc();
}
class all1 implements all {
@Override
public CFactory c() {
return new f1();
}
@Override
public Computer1 cc() {
return new c1();
}
}
class all2 implements all {
@Override
public CFactory c() {
return new f2();
}
@Override
public Computer1 cc() {
return new c2();
}
}
public class FactoryTest4 {
public void test1(Computer1 computer1) {
computer1.computer();
}
public void test2(CFactory cFactory) {
cFactory.factory();
}
public static void main(String[] args) {
FactoryTest4 factoryTest4 = new FactoryTest4();
all all1 = new all1();
Computer1 computer1=all1.cc();
CFactory cFactory=all1.c();
factoryTest4.test1(computer1);
factoryTest4.test2(cFactory);
}
}