针对接口编程,可以隔离掉以后系统可能发生的一大堆改变。为什么呢?如果代码是针对接口而写,那么通过多态,它可以与任何新类实现该接口。但是,当代码使用大量的具体类时,等于是自找麻烦,因为一旦加入新的具体类,就必须改变代码。也就是说,你的类并发“对修改”关闭。想用新的具体类型来扩展代码,必须重新打开它。
所以,该怎么办?当遇到这些问题时,就应该回到OO设计原则去寻找探索。我们的第一个原则用来处理改变,并帮助我们“找出会变化的方面,把他们从不变的部分分离出来”
原代码:
package com.learn.store;
import com.learn.entity.CheesePizza;
import com.learn.entity.GreekPizza;
import com.learn.entity.PepperoniPizza;
import com.learn.entity.Pizza;
import com.learn.factory.SimplePizzaFactory;
/**
* @author weijie
* @date 2020/7/8 11:05
*/
public class PizzaStore {
/**
* 预定比萨:
* 【压力来自于增加更过的比萨类型】
* 根据比萨类型,生成实例,但是这种缺点是以后需要动态添加、删除比萨时候,都需要改动这块代码
* @return
*/
Pizza orderPizza(String type){
Pizza pizza = null;
/**
* 为了应对压力吗,我们需要封装这块代码,抽出的对象变成工厂
*/
if (type.equals("cheese")){
pizza = new CheesePizza();
}else if (type.equals("greek")){
pizza = new GreekPizza();
}else if (type.equals("pepperoni")){
pizza = new PepperoniPizza();
}
}
package com.learn.entity;
/**
* @author weijie
* @date 2020/7/8 11:22
*/
public class Pizza {
public void prepare(){
System.out.println("准备 ...");
}
public void bake(){
System.out.println("烘焙 ...");
}
public void cut(){
System.out.println("切块 ...");
}
public void box(){
System.out.println("装盒子 ...");
}
}
package com.learn.entity;
/**
* @author weijie
* @date 2020/7/8 11:27
*/
public class CheesePizza extends Pizza {
@Override
public void prepare() {
System.out.println("CheesePizza");
super.prepare();
}
@Override
public void bake() {
super.bake();
}
@Override
public void cut() {
super.cut();
}
@Override
public void box() {
super.box();
}
}
package com.learn.entity;
/**
* @author weijie
* @date 2020/7/8 11:28
*/
public class GreekPizza extends Pizza {
@Override
public void prepare() {
System.out.println("GreekPizza");
super.prepare();
}
@Override
public void bake() {
super.bake();
}
@Override
public void cut() {
super.cut();
}
@Override
public void box() {
super.box();
}
}
package com.learn.entity;
/**
* @author weijie
* @date 2020/7/8 11:29
*/
public class PepperoniPizza extends Pizza {
@Override
public void prepare() {
System.out.println("PepperoniPizza");
super.prepare();
}
@Override
public void bake() {
super.bake();
}
@Override
public void cut() {
super.cut();
}
@Override
public void box() {
super.box();
}
}
package com.learn.factory;
import com.learn.entity.CheesePizza;
import com.learn.entity.GreekPizza;
import com.learn.entity.PepperoniPizza;
import com.learn.entity.Pizza;
/**
* 【建立一个简单比萨工厂】
* 改类主做一件事情,就是负责帮客户创建比萨
* @author weijie
* @date 2020/7/8 11:36
*/
public class SimplePizzaFactory {
public Pizza createPizza(String type){
Pizza pizza = null;
if (type.equals("cheese")){
pizza = new CheesePizza();
}else if (type.equals("greek")){
pizza = new GreekPizza();
}else if (type.equals("pepperoni")){
pizza = new PepperoniPizza();
}
return pizza;
}
}
package com.learn.store;
import com.learn.entity.Pizza;
import com.learn.factory.SimplePizzaFactory;
/**
* @author weijie
* @date 2020/7/8 11:05
*/
public class PizzaStore {
SimplePizzaFactory factory;
public PizzaStore(SimplePizzaFactory factory){
this.factory = factory;
}
public Pizza orderPizza(String type){
Pizza pizza = factory.createPizza(type);
/**
* 【如果想要对一些质量控制】
* 如果采用其他自创流程:采用不同的烘焙做法、不要切片、使用其他厂商盒子,此时没法控制
* 目前所有方法绑定的太死了,没有弹性
*/
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
}
运行:
package com.learn;
import com.learn.factory.SimplePizzaFactory;
import com.learn.store.PizzaStore;
/**
* @author weijie
* @date 2020/7/8 13:07
*/
public class Runner {
public static void main(String[] args) {
PizzaStore pizzaStore = new PizzaStore(new SimplePizzaFactory());
pizzaStore.orderPizza("greek");
}
}
输出:
Files\Java\jdk1.8.0_171\jre\lib\rt.jar;F:\lagou\design_pattern\target\classes" com.learn.Runner
GreekPizza
准备 ...
烘焙 ...
切块 ...
装盒子 ...
Process finished with exit code 0
将原来简单工厂,写出三种不同工厂,NYPizzaFactory(纽约工厂)、ChicagoPizzaFactory(芝加哥工厂)、CaliforniaPizzaFactory(加利福尼亚工厂)
public class CaliforniaPizzaFactory extends SimplePizzaFactory {
@Override
public Pizza createPizza(String type) {
System.out.println("CaliforniaPizzaFactory");
return super.createPizza(type);
}
}
public class ChicagoPizzaFactory extends SimplePizzaFactory {
@Override
public Pizza createPizza(String type) {
System.out.println("ChicagoPizzaFactory");
return super.createPizza(type);
}
}
public class NYPizzaFactory extends SimplePizzaFactory {
@Override
public Pizza createPizza(String type) {
System.out.println("NYPizzaFactory");
return super.createPizza(type);
}
}
运行:
public class Runner {
public static void main(String[] args) {
PizzaStore pizzaStore = new PizzaStore(new ChicagoPizzaFactory());
pizzaStore.orderPizza("greek");
}
}
输出:
Files\Java\jdk1.8.0_171\jre\lib\rt.jar;F:\lagou\design_pattern\target\classes" com.learn.Runner
ChicagoPizzaFactory
GreekPizza
准备 ...
烘焙 ...
切块 ...
装盒子 ...
如果采用其他自创流程:采用不同的烘焙做法、不要切片、使用其他厂商盒子,此时没法控制
目前所有方法绑定在PizzaStore,没有弹性。
将PizzaStore加抽象方法
public abstract class PizzaStore {
Pizza orderPizza(String type){
Pizza pizza = createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
abstract Pizza createPizza(String type);
}
现在已经有一个PizzaStore超类:让每个域类型:NYPizzaStore(纽约披萨店)、ChicagoPizzaStore(芝加哥披萨店)、CaliforniaPizzaStore(加利福尼亚披萨)都继承PizzaStore
public class NYPizzaStore extends PizzaStore {
NYPizzaFactory factory;
public NYPizzaStore(NYPizzaFactory factory) {
this.factory = factory;
}
public Pizza createPizza(String type) {
System.out.println("NYPizzaStore");
return factory.createPizza(type);
}
}
public class ChicagoPizzaStore extends PizzaStore {
ChicagoPizzaFactory factory;
public ChicagoPizzaStore(ChicagoPizzaFactory factory) {
this.factory = factory;
}
public Pizza createPizza(String type) {
System.out.println("ChicagoPizzaStore");
return factory.createPizza(type);
}
}
public class CaliforniaPizzaStore extends PizzaStore {
CaliforniaPizzaFactory factory;
public CaliforniaPizzaStore(CaliforniaPizzaFactory factory) {
this.factory = factory;
}
public Pizza createPizza(String type) {
System.out.println("CaliforniaPizzaStore");
return factory.createPizza(type);
}
}
运行:
public class Runner {
public static void main(String[] args) {
NYPizzaStore nyPizzaStore = new NYPizzaStore(new NYPizzaFactory());
nyPizzaStore.orderPizza("cheese");
}
}
输出:
NYPizzaStore
NYPizzaFactory
CheesePizza
准备 ...
烘焙 ...
切块 ...
装盒子 ...
public class NYPizzaStore extends PizzaStore {
NYPizzaFactory factory;
public NYPizzaStore(NYPizzaFactory factory) {
this.factory = factory;
}
public Pizza createPizza(String type) {
System.out.println("NYPizzaStore");
return factory.createPizza(type);
}
}
public class NYPizzaFactory extends SimplePizzaFactory {
@Override
public Pizza createPizza(String type){
Pizza pizza = null;
if (type.equals("cheese")){
pizza = new NYStyleCheesePizza();
}else if (type.equals("veggie")){
pizza = new NYStyleVeggiePizza();
}else if (type.equals("clam")){
pizza = new NYStyleClamPizza();
}else if (type.equals("pepperoni")){
pizza = new NYStylePepperoniPizza();
}else {
return null;
}
return pizza;
}
}
public class ChicagoStyleCheesePizza extends Pizza {
public ChicagoStyleCheesePizza() {
name = "深盘奶酪披萨";
dough = "特厚皮面团";
sauce = "李形番茄";
toppings.add("切碎的Mozzarella酱");
}
@Override
public void cut() {
System.out.println("切成方形");
}
}
public class NYStyleCheesePizza extends Pizza {
public NYStyleCheesePizza() {
name = "酱汁和奶酪披萨";
dough = "薄皮面团";
sauce = "纯番茄酱";
toppings.add("磨碎的Reggiano奶酪");
}
}
public class Runner {
public static void main(String[] args) {
NYPizzaStore nyPizzaStore = new NYPizzaStore(new NYPizzaFactory());
ChicagoPizzaStore chicagoPizzaStore = new ChicagoPizzaStore(new ChicagoPizzaFactory());
nyPizzaStore.orderPizza("cheese");
chicagoPizzaStore.orderPizza("cheese");
}
}
输出:
NYPizzaStore
准备 ...
磨碎的Reggiano奶酪
烘焙 ...
切块 ...
装盒子 ...
ChicagoPizzaStore
准备 ...
切碎的Mozzarella酱
烘焙 ...
切成方形
装盒子 ...
所有工厂模式都用来封装对象的创建,工厂方法模式通过让子类决定改创建的对象是什么,来达到将对象创建的过程封装的目的·让我们看看类图有哪些组成元素
将一个orderPizza()方法和一个工厂方法联合起来,就可以成为一个框架。除此之外,工厂方法将生产知识封装进各个创建者,这样的做法也可以被视为是一种框架,让我们来看看两个平行的类层级,认清它们关系