Java中的设计模式(五):工厂模式

302 阅读5分钟

image.png

基本概念

工厂模式思想就是把创建实例的代码抽离出来放到一个专属的类中去管理和维护,从这一点也可以看出符合了单一职责原则,这样彻底把实例创建和调用者之间的耦合关系降低,项目后期的管理和维护性将得到进一步的提高!。

工厂模式 (Singleton pattern)是 创建型设计模式 的一种,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

工厂模式分为简单工厂模式的工厂模式、工厂方法模式的工厂模式和抽象工厂模式的工厂模式!

1. 简单工厂模式(静态工厂模式)

public interface PeaceMaster {
    void specially();
}

先定义一个“和平精英”的接口

//和平精英正式服对象

public class RealPeaceMaster implements PeaceMaster {
    public void specially(){
        System.*out*.println("我是正式服,我会提供更稳定的服务给各位特种兵!");
    }
}

创建一个具体的“和平精英”正式服对象类来实现“和平精英”接口,并重写接口方法

//和平精英体验服对象

public class TastePeaceMaster implements PeaceMaster {
    public void specially(){
        System.*out*.println("我是体验服,我会提供更多的新玩法给各位特种兵!");
    }
}

创建一个具体的“和平精英”体验服对象类来实现“和平精英”接口,并重写接口方法

public class SimpleFactory {
    public static PeaceMaster getInstant(String type){
        PeaceMaster peaceMaster=null;
        switch (type){
            case "taste":
                peaceMaster=new TastePeaceMaster();\
                return peaceMaster;\
            case "real":
                peaceMaster=new RealPeaceMaster();\
                return peaceMaster;\
            default:
                throw new RuntimeException("为输入获取类型或类型找不到");\
       }
   }
}

创建一个简单工厂对象类,创建一个获取对象工厂方法,根据传入不同的需求去返回不同的“和平精英”对象

public static void main(String[] args) {
    //获取体验服对象
    PeaceMaster taste1 = SimpleFactory.*getInstant*("taste");
    taste1.specially();
    //获取一个未定义的对象,结果肯定会报异常
    PeaceMaster taste = SimpleFactory.*getInstant*("tast");
    taste.specially();
}

image.png 我们可以看到前一个正确获取的“和平精英体验服”对象已经拿到并且成功执行了其内部方法,后面一个因为获取的类型未定义所以会抛一个我们自定义的异常对象!

由此我们可以看出通过这个工厂类我们可以直接调用这个类的方法就可以轻松获取定义的类型的所有对象!但是这个设计也有不小的缺点就是违背了开闭原则(OCP),扩展性特别差,如果我们后期需要添加其他的“和平精英”对象子类型就必须去修改工厂类。

2. 工厂方法模式

//腾讯游戏

public interface TenCentGame {
   void intro();
}

定义一个游戏的总接口

public class King implements TenCentGame{
    @Override
    public void intro() {
        System.*out*.println("欢迎来到王者荣耀!");
    }
}
public class PeaceMaster implements TenCentGame{
    @Override
    public void intro() {
        System.*out*.println("欢迎来到和平精英,特种兵!");
    }
}

创建两个具体的游戏实现类

public interface TenCentGameFactory {
    TenCentGame createGame();
}

创建一个总工厂接口,并定义一个抽象方法便于子工厂的具体实现!

public class KingFactory implements TenCentGameFactory {
    @Override
    public TenCentGame createGame() {
        return new King();
    }
}
public class PeaceMasterFactory implements TenCentGameFactory{
   @Override
   public TenCentGame createGame() {
       return new PeaceMaster();
   }
}

两个子工厂分别实现抽象工厂的接口方法返回各自所需生产的对象

public static void main(String[] args) {
    TenCentGameFactory centGameFactory=new PeaceMasterFactory();
    TenCentGame game = centGameFactory.createGame();
    game.intro();
}

客户端进行调用只需创建顶级的抽象工厂实例,调用其中的创建业务所需实例的方法就可以得到所需的具体实例,通过该实例进行业务逻辑等方法处理业务!缺点也很明显某个某个产品类需要进行一定的修改,很可能需要修改对应的工厂类。如果产品类很多的话,工厂类修改就会相当麻烦!

3.抽象工厂模式

这个模式是基于工厂方法模式的一个扩展,很类似但不是同一个对象

public interface TenCentGame {
    void intro();
}

定义顶级接口,并定义一个抽象方法给下面具体子类去实现

public interface King extends TenCentGame{
    @Override
    void intro();
}
public interface PeaceMaster extends TenCentGame{
    @Override
    void intro();
}

用子接口继承过来,目的在于降低与具体类之间的耦合度

//王者正式服

public class RealKing implements King{
    @Override
    public void intro() {
        System.*out*.println("欢迎来到王者荣耀正式服!");
    }
}

//吃鸡正式服

public class RealPeaceMaster implements PeaceMaster{
    @Override
    public void intro() {
        System.*out*.println("欢迎来到和平精英正式服!");
    }
}

//王者体验服

public class TasteKing implements King{
    @Override
    public void intro() {
        System.*out*.println("欢迎来到王者荣耀体验服!");
    }
}

//吃鸡体验服

public class TastePeaceMaster implements PeaceMaster{
    @Override
    public void intro() {
        System.*out*.println("欢迎来到和平精英体验服!");
    }
}

上面就是具体的子类去实现了,下面开始实现工厂类的设计

public interface TenCentFactory {
    TenCentGame createRealGame();
    TenCentGame createTasteGame();
}
public class KingFactory implements TenCentFactory{
    @Override
    public TenCentGame createRealGame() {
        return new RealKing();
    }
    @Override
    public TenCentGame createTasteGame() {
        return new TasteKing();
    }
}
public class PeaceMasterFactory implements TenCentFactory{
    @Override
    public TenCentGame createRealGame() {
        return new RealPeaceMaster();
    }
    @Override
    public TenCentGame createTasteGame() {
        return new TastePeaceMaster();
    }
}

看到这里大家相比就会了解很多了,这个和上面的工厂方法模式最大区别已经出来了,

  1. 工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。  
  2. 工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个产品类实例。

但是该说不是,缺点也很明显应付不了新的产品种类的加入,一旦新产品加入就必须再写一个新的工厂子类的实现,这样扩展性就下降了不少。

优点也不容忽视,抽象工厂将应用中的产品集合确定了,分别进行归类处理,将同一系列的实例放在一起有利于设计和降低与其他业务实例的耦合度。

总结:工厂三兄弟都有各自的好处与缺点,没有一味的好与不好,只是在不同的业务环境下哪种更适合,具体的安排还是要看大家的业务逻辑是如何写的。

转载自:developer.aliyun.com/article/788…