객체지향 프로그래밍에서 가장 일반적인 방법은 객체 인스턴스를 생성하는 new 연산자이며, new 연산자는 객체 인스턴스를 생성하는 데 사용됩니다. 그러나 어떤 경우에는 new 연산자가 객체를 직접 생성하면 몇 가지 문제가 발생할 수 있습니다. 예를 들어, 다양한 유형의 객체를 생성하려면 일련의 단계가 필요합니다. 객체의 초기 설정을 계산하거나 획득해야 할 수도 있고, 생성할 하위 객체 인스턴스를 선택하거나, 필요한 객체를 생성하기 전에 일부 도우미 객체를 생성해야 할 수도 있습니다. . 이러한 경우 새로운 객체를 생성하는 것은 더 큰 기계의 기어 변속기와 같은 단순한 작업이 아닌 "프로세스"입니다.
패턴의 문제점: 객체 인스턴스를 구성하는 세부 사항과 복잡한 프로세스에 대해 걱정할 필요 없이 어떻게 쉽고 편리하게 객체 인스턴스를 구성할 수 있습니까?
해결책: 공장을 지어 물건을 만들다
구현:
1. 소개
1) 아직 공장 시대는 없다: 산업 혁명이 없다면, 고객이 BMW 자동차를 원하는 경우, 일반적인 접근 방식은 고객이 BMW 자동차를 만든 후 사용하는 것입니다.
2) 단순 공장 모델: 이후 산업 혁명이 나타났습니다. 사용자는 BMW 자동차를 만들 필요가 없습니다. 고객이 BMW를 만드는 데 도움을 줄 수 있는 공장이 있기 때문입니다. 이 공장에서는 고객이 원하는 모든 자동차를 만들 수 있습니다. 예를 들어, 저는 320i 시리즈 자동차를 원합니다. 공장에서는 이러한 일련의 자동차를 생산합니다. 즉, 공장에서는 제품을 생산할 수 있습니다.
3) 팩토리 방식 모델 시대: 고객 만족을 위해 320i, 523i, 30li 등 BMW 자동차 시리즈가 점점 더 많아지고 있으며, 하나의 공장에서 모든 BMW 시리즈를 만들 수는 없습니다. 그 결과 여러 특정 공장이 분리되었습니다. 각 특정 식물은 일종의 시리즈를 만듭니다. 즉, 특정 팩토리 클래스는 하나의 특정 제품만 생성할 수 있습니다. 그러나 BMW 공장은 여전히 추상화에 불과하다. 자동차를 생산하려면 특정 공장을 지정해야 합니다.
4) 추상적인 공장 모델 시대: 고객의 요구 사항이 점점 높아지면서 BMW 자동차에는 에어컨이 장착되어야 합니다. 그래서 공장에서는 BMW 자동차와 필요한 에어컨을 생산하기 시작했습니다.
결국 고객은 BMW 영업사원에게 '나는 에어컨이 설치된 523i 자동차를 원합니다. 그러면 영업사원이 에어컨이 설치된 523i 자동차를 직접 줄 것입니다'라고 말하면 됩니다. 523i 에어컨이 장착된 BMW 자동차를 직접 제작하는 대신
공장 모델입니다.
2. 분류
팩토리 패턴은 주로 객체 생성을 위한 전환 인터페이스를 제공하여 유연성 향상이라는 목적을 달성하기 위해 객체 생성의 특정 프로세스를 보호하고 격리합니다.
팩토리 패턴은 세 가지 카테고리로 나눌 수 있습니다.
1) 단순 팩토리 패턴(Simple Factory)
2) 팩토리 메소드 패턴(Factory Method)
3) 추상 팩토리 패턴(Abstract) Factory)
이 세 가지 모드는 위에서 아래로 점차 추상화되어 보다 일반화됩니다.
GOF는 책 "Design Patterns"에서 팩토리 패턴을 팩토리 메소드 패턴(Factory Method)과 추상 팩토리 패턴(Abstract Factory)의 두 가지 범주로 나눕니다.
Simple Factory 패턴(Simple Factory)을 Factory Method 패턴의 특별한 경우로 생각하면 둘은 같은 카테고리로 분류됩니다.
3. 차이점
팩토리 메소드 패턴:
추상 제품 클래스는 여러 특정 제품 클래스를 파생할 수 있습니다.
추상 팩토리 클래스는 여러 개의 구체적인 팩토리 클래스를 파생할 수 있습니다.
각 특정 공장 클래스는 특정 제품 클래스의 인스턴스를 하나만 생성할 수 있습니다.
추상 팩토리 패턴:
여러 추상 제품 클래스, 각 추상 제품 클래스는 여러 특정 제품 클래스를 파생할 수 있습니다.
추상 팩토리 클래스는 여러 개의 구체적인 팩토리 클래스를 파생할 수 있습니다.
각 특정 공장 클래스는 특정 제품 클래스의 여러 인스턴스를 생성할 수 있습니다.
차이점:
팩토리 메소드 패턴에는 추상 제품 클래스가 하나만 있는 반면 추상 팩토리 패턴에는 여러 개가 있습니다.
팩토리 메소드 패턴의 구체적인 팩토리 클래스는 특정 제품 클래스의 인스턴스를 하나만 생성할 수 있는 반면, 추상 팩토리 패턴은 여러 인스턴스를 생성할 수 있습니다.
둘 다 사용할 수 있습니다.
4. 단순 팩토리 패턴
팩토리(함수 또는 클래스 메소드)를 생성하여 새로운 객체를 생성합니다.
배포 설명 소개: 처음부터. 고객은 자신만의 BMW 자동차를 만들어 사용합니다.
public class BMW320 { public BMW320(){ System.out.println("制造-->BMW320"); } } public class BMW523 { public BMW523(){ System.out.println("制造-->BMW523"); } } public class Customer { public static void main(String[] args) { BMW320 bmw320 = new BMW320(); BMW523 bmw523 = new BMW523(); } }
고객은 자동차를 만드는 방법을 알아야 하며, 고객과 자동차가 긴밀하게 결합되는 커플링을 줄이기 위해 팩토리 클래스가 등장했습니다. BMW의 운영 내용을 공장에 담는다. 고객이 직접 공장의 공장 제작 방식을 이용해 제작 내용을 알 필요 없이 원하는 BMW 모델을 전달하는 것이 산업혁명이다.
즉, 새로운 객체를 생성하기 위해 팩토리 클래스 메소드를 생성합니다. 그림과 같이:
제품 카테고리:
abstract class BMW { public BMW(){ } } public class BMW320 extends BMW { public BMW320() { System.out.println("制造-->BMW320"); } } public class BMW523 extends BMW{ public BMW523(){ System.out.println("制造-->BMW523"); } }
공장 카테고리:
public class Factory { public BMW createBMW(int type) { switch (type) { case 320: return new BMW320(); case 523: return new BMW523(); default: break; } return null; } }
고객 카테고리:
public class Customer { public static void main(String[] args) { Factory factory = new Factory(); BMW bmw320 = factory.createBMW(320); BMW bmw523 = factory.createBMW(523); } }
简单工厂模式又称静态工厂方法模式。重命名上就可以看出这个模式一定很简单。它存在的目的很简单:定义一个用于创建对象的接口。
先来看看它的组成:
1) 工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑,用来创建产品
2) 抽象产品角色:它一般是具体产品继承的父类或者实现的接口。
3) 具体产品角色:工厂类所创建的对象就是此角色的实例。在Java中由一个具体类实现。
下面我们从开闭原则(对扩展开放;对修改封闭)上来分析下简单工厂模式。当客户不再满足现有的车型号的时候,想要一种速度快的新型车,只要这种车符合抽象产品制定的合同,那么只要通知工厂类知道就可以被客户使用了。所以对产品部分来说,它是符合开闭原则的;但是工厂部分好像不太理想,因为每增加一种新型车,都要在工厂类中增加相应的创建业务逻辑(createBMW(int type)方法需要新增case),这显然是违背开闭原则的。可想而知对于新产品的加入,工厂类是很被动的。对于这样的工厂类,我们称它为全能类或者上帝类。
我们举的例子是最简单的情况,而在实际应用中,很可能产品是一个多层次的树状结构。由于简单工厂模式中只有一个工厂类来对应这些产品,所以这可能会把我们的上帝累坏了,也累坏了我们这些程序员。
于是工厂方法模式作为救世主出现了。 工厂类定义成了接口,而每新增的车种类型,就增加该车种类型对应工厂类的实现,这样工厂的设计就可以扩展了,而不必去修改原来的代码。
五、工厂方法模式
工厂方法模式去掉了简单工厂模式中工厂方法的静态属性,使得它可以被子类继承。这样在简单工厂模式里集中在工厂方法上的压力可以由工厂方法模式里不同的工厂子类来分担。
工厂方法模式组成:
1)抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。
2)具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。
3)抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。
4)具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。
工厂方法模式使用继承自抽象工厂角色的多个子类来代替简单工厂模式中的“上帝类”。正如上面所说,这样便分担了对象承受的压力;而且这样使得结构变得灵活 起来——当有新的产品产生时,只要按照抽象产品角色、抽象工厂角色提供的合同来生成,那么就可以被客户使用,而不必去修改任何已有 的代码。可以看出工厂角色的结构也是符合开闭原则的!
代码如下:
产品类:
abstract class BMW { public BMW(){ } } public class BMW320 extends BMW { public BMW320() { System.out.println("制造-->BMW320"); } } public class BMW523 extends BMW{ public BMW523(){ System.out.println("制造-->BMW523"); } }
创建工厂类:
interface FactoryBMW { BMW createBMW(); } public class FactoryBMW320 implements FactoryBMW{ @Override public BMW320 createBMW() { return new BMW320(); } } public class FactoryBMW523 implements FactoryBMW { @Override public BMW523 createBMW() { return new BMW523(); } }
客户类:
public class Customer { public static void main(String[] args) { FactoryBMW320 factoryBMW320 = new FactoryBMW320(); BMW320 bmw320 = factoryBMW320.createBMW(); FactoryBMW523 factoryBMW523 = new FactoryBMW523(); BMW523 bmw523 = factoryBMW523.createBMW(); } }
工厂方法模式仿佛已经很完美的对对象的创建进行了包装,使得客户程序中仅仅处理抽象产品角色提供的接口,但使得对象的数量成倍增长。当产品种类非常多时,会出现大量的与之对应的工厂对象,这不是我们所希望的。