java工厂模式 #4

Posted 6 years ago · 1 mins reading

Spring的笔记写了一半,突然想复习一下工厂模式,所以写一篇。

前言

面向对象设计的基本原则

谈到工厂模式我要先提一下,面向对象设计的基本原则:

  1. 单一职责原则(Single Responsibility Principle)

    每一个类应该专注于做一件事情。

  1. 里氏替换原则(Liskov Substitution Principle)

    超类存在的地方,子类是可以替换的。

  2. 依赖倒置原则(Dependence Inversion Principle)

    实现尽量依赖抽象,不依赖具体实现。

  3. 接口隔离原则(Interface Segregation Principle)

    应当为客户端提供尽可能小的单独的接口,而不是提供大的总的接口。

  4. 迪米特法则(Law Of Demeter)

    又叫最少知识原则,一个软件实体应当尽可能少的与其他实体发生相互作用。

  5. 开闭原则(Open Close Principle)

    面向扩展开放,面向修改关闭。

  6. 组合/聚合复用原则(Composite/Aggregate Reuse Principle CARP)

    尽量使用组合/聚合达到复用,尽量少用继承。原则: 一个类中有另一个类的对象。

工厂模式的核心本质

  1. 通过用工厂的方法来new对象,来实现对象的实例化。
  2. 调用者和实现者 相互解藕

简单工厂模式

简单工厂模式,虽然简单,但是它也是最常用的工厂模式。

什么都不说,这章,我们直接撸代码。

先来个狗的抽象类。

java
public interface Dog{
void bark();
}

再来个旺财的实现类。

java
public class Money implements Dog{
@Override
public void bark(){
system.out.println("旺财叫!");
}
}

然后来个来福的实现类。

java
public class Lucky implements Dog{
@Override
public void bark(){
system.out.println("来福叫!");
}
}

现在我们的依赖关系为:

text
Dog <——- Money
^
|—<——-Lucky

如果我们平时想要调用这两个实现类,我们通常会这样:

java
public class client{
public static void main(String\[\] args){
Dog money = new Money();
Dog Lucky = new Lucky();
money.bark();
Lucky.barck();
}
}

输出应该是:

旺财叫!
来福叫!

这样造成的问题是:
client既要知道Dog,还要知道Dog的分类才能调用成功。

然后我们来一个Dog的工厂类

java
public class DogFactory{
public static Dog getDog(String type){
switch(type){
case "Money":
return new Money();
break;
case "Lucky":
return new Lucky();
break;
default:
throw new DogNotFoundException(DOG_NOT_FOUND);
}
}
}

然后我们就可以这样那拿到我们想要的狗了:

java
public class Client{
public static void main(String\[\] args){
Dog money = DogFactory.getDog("Money");
Dog Lucky = DogFactory.getDog("Lucky");
money.bark();
Lucky.barck();
}
}

输出应该还是:

旺财叫!
来福叫!

现在的依赖关系虽然较复杂,但是已经很解藕了。

现在客户端,只需要知道,我要Dog,我要什么狗。然后就不亲自去造狗,而是直接去找工厂要。工厂知道后,就开始找有没有这个狗,有就返回给客户端,没有嘛,就报一个简单的异常。

然后,你不止可以选择switch的方式来创建工厂类还可以用if else和静态方法调用。

if else

java
public class DogFactory{
public static Dog getDog(String type){
if("Money".equals(type)){
return new Money();
}else("Lucky".equals(type)){
return new Lucky();
}
// 异常省略了。
}
}

静态方法

java
public class DogFactory{
public static Dog getMoney(){
return new Money();
}
public static Dog getLucky(){
return new Lucky();
}
}

当然工厂模式的命名以 createXX 更好,但是我总觉得创造一个 旺财怪怪的,所以改成了get。

工厂方法模式

我们还是先搞三个类

java
public interface Dog{
void bark();
}
java
public class Money implements Dog{
@Override
public void bark(){
system.out.println("旺财叫!");
}
}
java
public class Lucky implements Dog{
@Override
public void bark(){
system.out.println("来福叫!");
}
}

这个模式,每个实现类都需要自己的工厂类

所以我们创建 旺财 和 来福 各自的工厂类 还有 Dog工厂的抽象类

java
public interface DogFactory{
Dog getDog();
}
java
public class MoneyFactory implements DogFactory{
@Override
public Dog getDog(){
return new Money();
}
}
java
public class LuckyFactory implements DogFactory{
@Override
public Dog getDog(){
return new Lucky();
}
}

然后写客户端

java
public class Client{
public static void main(String [] args){
Money money = MoneyFactory.getDog();
Lucky lucky = LuckyFactory.getDog();
money.bark();
Lucky.bark();
}
}

这样就保证了开闭原则,扩展时不修改原有代码,但是类太XX多了。
我也认为这样设计很蠢,贼蠢。

抽象工厂模式

抽象工厂模式,是为了解决多层次情况。比如:我们现在把来福和旺财看成两类狗,然后再加入狗的颜色属性

然后我们需要输出也就是得到:

例如:

黑色旺财叫!

白色旺财叫!

黑色来福叫!

白色来福叫!

核心思想就是,我们通过工厂类来指定一个来福工厂类还是旺财工厂类,
然后用它们各自工厂类的创建狗方法来生成上面的结果。

然后我们再让整体结构复杂一点,添加点属性。

所以我们的整体结构现在变成了现在这个样子:

白色狗抽象类和具体实现类

java
public interface WhiteDog{
void bark();
}
public class MoneyWhiteDog implements WhiteDog{
public void bark(){
sout("白色旺财叫!")
};
}
public class LuckyWhiteDog implements WhiteDog{
public void bark(){
sout("白色来福叫!")
};
}

黑色狗抽象类和具体实现类

java
public interface BlackDog{
void bark();
}
java
public class MoneyBlackDog implements BlackDog{
public void bark(){
sout("黑色旺财叫!")
};
}
java
public class LuckyBlackDog implements BlackDog{
public void bark(){
sout("黑色来福叫!")
};
}

狗的工厂抽象类

java
public interface DogFactory{
WhiteDog createWhiteDog();
BlackDog createBlackDog();
}

旺财工厂类

java
public class MoneyFactory implements DogFactory{
@Override
WhiteDog createWhiteDog(){
return new MoneyWhiteDog;
};
BlackDog createBlackDog(){
return new MoneyBlackDog
};
}

来福工厂类

java
public class LuckyFactory implements DogFactory{
@Override
WhiteDog createWhiteDog(){
return new LuckyWhiteDog;
};
BlackDog createBlackDog(){
return new LuckyBlackDog
};
}
java
public static void main(String [] args){
DogFactory dogFactory = new MoneyFactory();
MoneyWhiteDog moneyWhiteDog = dogFactory.createWhiteDog();
moneyWhiteDog.bark();
}

如果不出意外的话,输出是:“白色旺财叫!”