原文:https://blog.youkuaiyun.com/lmj623565791/article/details/24460585
设计模式分为3种类型,共23种。
创建型模式: 单例模式 ,抽象工厂模式, 建造者模式 , 工厂模式, 原型模式
结构型模式: 适配器模式, 桥接模式 ,装饰模式 ,组合模式,外观模式 ,享元模式, 代理模式。
行为型模式:模板方式模式, 命令模式, 迭代器模式, 观察者模式 ,中介者模式 ,备忘录模式,解释器模式,状态模式,
策略模式,职责链模式 访问者模式。
下面这篇文章围绕工厂模式展开。
工厂模式中主要包括 静态工厂模式 简单工厂模式 工厂方法模式 抽象工厂模式。
本篇文章主要参考张鸿洋博客展开 仿照他写的博客写了一个例子,边看边写,印象会更深一点。
目录
1.静态工厂模式
这个比较常见,项目中的辅助类,TextUtil.isEmpty (类+静态方法)
2.简单工厂模式(常见)
接下来我们将围绕简单工厂模式展开一个“卖肉夹馍”的例子。
2.1 准备一个生产肉夹馍的工厂。
2.2 拥有一个生产肉夹馍的工厂以后,我们需要一个卖肉夹馍的店
2.3 接下来就是各种各样的肉夹馍了
代码中所有的类:
这样一种方式的好处就是卖肉夹馍的店只要专心卖肉夹馍 ,制作肉夹馍的工厂专心做肉夹馍。即使增加或者减少肉夹馍的种类也与卖肉夹馍的店无关。
2.1 RouJiaMo
package com.soup.redis.common;
/**
* @Author tanghh
* @Date 2020/7/17 14:48
*/
public abstract class RouJiaMo {
protected String name;
/**
* 准备工作
*/
public void prepare() {
System.out.println("揉面-剁肉-完成准备工作");
}
/**
* 使用你们的专用袋-包装
*/
public void pack() {
System.out.println("肉夹馍-专用袋-包装");
}
/**
* 秘制设备-烘烤2分钟
*/
public void fire() {
System.out.println("肉夹馍-专用设备-烘烤");
}
}
2.2 各种风味的肉夹馍
package com.soup.redis.common;
/**
* @Author tanghh
* @Date 2020/7/17 14:50
*/
public class LaRouJiaMo extends RouJiaMo {
public LaRouJiaMo(){
this.name = "辣味肉夹馍";
}
}
package com.soup.redis.common;
/**
* @Author tanghh
* @Date 2020/7/17 14:53
*/
public class SuanRouJiaMo extends RouJiaMo {
public SuanRouJiaMo(){
this.name = "酸味肉夹馍";
}
}
package com.soup.redis.common;
/**
* @Author tanghh
* @Date 2020/7/17 14:51
*/
public class TianRouJiaMo extends RouJiaMo {
public TianRouJiaMo (){
this.name = "甜味肉夹馍";
}
}
2.3 制作肉夹馍的工厂
package com.soup.redis.factory;
import com.soup.redis.common.LaRouJiaMo;
import com.soup.redis.common.RouJiaMo;
import com.soup.redis.common.SuanRouJiaMo;
import com.soup.redis.common.TianRouJiaMo;
/**
* @Author tanghh
* @Date 2020/7/17 14:46
*/
public class SimpleRouJiaMoFactory {
public RouJiaMo createRouJiaMo(String type) {
RouJiaMo rouJiaMo = null;
if (type.equals("Suan")) {
System.out.println("酸味肉夹馍");
rouJiaMo = new SuanRouJiaMo();
} else if (type.equals("Tian")) {
System.out.println("甜味肉夹馍");
rouJiaMo = new TianRouJiaMo();
} else if (type.equals("La")) {
System.out.println("辣味肉夹馍");
rouJiaMo = new LaRouJiaMo();
}
return rouJiaMo;
}
}
2.4 卖肉夹馍的店
package com.soup.redis.store;
import com.soup.redis.common.RouJiaMo;
import com.soup.redis.factory.SimpleRouJiaMoFactory;
/**
* @Author tanghh
* 卖肉夹馍的店
* @Date 2020/7/17 14:54
*/
public class RoujiaMoStore {
/**
* 根据传入类型卖不同的肉夹馍
*
* @param type
* @return
*/
public RouJiaMo sellRouJiaMo(String type) {
SimpleRouJiaMoFactory factory = new SimpleRouJiaMoFactory();
RouJiaMo rouJiaMo = factory.createRouJiaMo(type);
rouJiaMo.prepare();
rouJiaMo.fire();
rouJiaMo.pack();
return rouJiaMo;
}
}
package com.soup.redis.test;
import com.soup.redis.store.RoujiaMoStore;
/**
* @Author tanghh
* @Date 2020/7/17 14:58
*/
public class FactoryTest {
public static void main(String[]args){
//卖肉夹馍
RoujiaMoStore store = new RoujiaMoStore();
store.sellRouJiaMo("La");
}
}
3.工厂方法模式
定义:定义一个创建对象的的接口,但由子类决定要实例化的类是哪一个,工厂方法模式把类实例化的过程推迟到子类。
接下来建立一个开连锁店的例子,此时我们在西安开一个分店。总店在上海。
工厂模式方式跟简单工厂模式不一样的地方在于 子类来决定生产什么类型的肉夹馍,总店提供秘方,而且分店总数一多的话,简单工厂模式里面的工厂里面的if就太多了。
3.1 定义一个卖肉夹馍的店,总店提供生产肉夹馍的方法。
3.2 西安开了一个分店,得到总店的生成肉夹馍的方法以后,就自己制作属于自己的肉夹馍。
例子涉及的所有类:
3.1 生产肉夹馍的总店
package com.soup.redis.store;
import com.soup.redis.common.RouJiaMo;
/**
* @Author tanghh
* 卖肉夹馍的店
* @Date 2020/7/17 14:54
*/
public abstract class RoujiaMoStore {
/**
* 创建肉夹馍的方法
* @param type
* @return
*/
public abstract RouJiaMo createRouJiaMo(String type);
/**
* 根据传入类型卖不同的肉夹馍
*
* @param type
* @return
*/
public RouJiaMo sellRouJiaMo(String type) {
//制作肉夹馍
RouJiaMo rouJiaMo = createRouJiaMo(type);
rouJiaMo.prepare();
rouJiaMo.fire();
rouJiaMo.pack();
return rouJiaMo;
}
}
3.2 西安的肉夹馍分店
package com.soup.redis.store;
import com.soup.redis.common.RouJiaMo;
import com.soup.redis.common.XianLaRouJiaMo;
import com.soup.redis.common.XianSuanRouJiaMo;
import com.soup.redis.common.XianTianRouJiaMo;
/**
* @Author tanghh
* @Date 2020/7/17 15:16
* 西安卖肉夹馍的店
*/
public class XianRouJiaMoStore extends RoujiaMoStore {
@Override
public RouJiaMo createRouJiaMo(String type) {
RouJiaMo rouJiaMo = null;
if (type.equals("Suan")) {
System.out.println("西安酸味肉夹馍");
rouJiaMo = new XianSuanRouJiaMo();
} else if (type.equals("Tian")) {
System.out.println("西安甜味肉夹馍");
rouJiaMo = new XianTianRouJiaMo();
} else if (type.equals("La")) {
System.out.println("西安辣味肉夹馍");
rouJiaMo = new XianLaRouJiaMo();
}
return rouJiaMo;
}
}
3.3 各种风味的具有西安特色的肉夹馍
package com.soup.redis.common;
/**
* @Author tanghh
* @Date 2020/7/17 14:48
*/
public abstract class RouJiaMo {
protected String name;
/**
* 准备工作
*/
public void prepare() {
System.out.println("揉面-剁肉-完成准备工作");
}
/**
* 使用你们的专用袋-包装
*/
public void pack() {
System.out.println("肉夹馍-专用袋-包装");
}
/**
* 秘制设备-烘烤2分钟
*/
public void fire() {
System.out.println("肉夹馍-专用设备-烘烤");
}
}
package com.soup.redis.common;
/**
* @Author tanghh
* @Date 2020/7/17 15:19
*/
public class XianLaRouJiaMo extends RouJiaMo {
public XianLaRouJiaMo (){
this.name = "西安辣味肉夹馍";
}
}
package com.soup.redis.common;
/**
* @Author tanghh
* @Date 2020/7/17 15:18
*/
public class XianSuanRouJiaMo extends RouJiaMo {
public XianSuanRouJiaMo(){
this.name="西安的酸味肉夹馍";
}
}
package com.soup.redis.common;
/**
* @Author tanghh
* @Date 2020/7/17 15:22
*/
public class XianTianRouJiaMo extends RouJiaMo {
public XianTianRouJiaMo(){
this.name = "西安的甜味肉夹馍";
}
}
4.抽象方法模式
定义:提供一个接口,用于创建相关的或依赖对象的家族,而不需要明确指定具体类。
接着上面连锁店的例子来说,为了建立一个良好的品牌形象,公司决定在各个城市建立自己的原料厂,保证高质量原料的供应。
4.1 总公司新建一个提供原料的生产接口, 西安分店根据当地特色提供材料。
4.2 接下来修改肉夹馍生产接口,肉夹馍中的肉 ,调料都需要调用总店的原料。
4.3 最后测试。
例子所涉及的代码和类:
4.1 总公司新建一个提供原料的生产接口, 西安分店根据当地特色提供材料。
package com.soup.redis.factory;
import com.soup.redis.common.Meat;
import com.soup.redis.common.YuanLiao;
/**
* @Author tanghh
* @Date 2020/7/17 15:44
*/
public interface RouJiaMoYLFactroy {
/**
* 生产肉
* @return
*/
Meat createMeat();
/**
* 生产调料神马的
* @return
*/
YuanLiao createYuanliao();
}
package com.soup.redis.factory;
import com.soup.redis.common.FreshMeat;
import com.soup.redis.common.LaWeiYuanLiao;
import com.soup.redis.common.Meat;
import com.soup.redis.common.YuanLiao;
/**
* @Author tanghh
* @Date 2020/7/17 15:45
*/
public class XianRouJiaMoYLFactroy implements RouJiaMoYLFactroy {
@Override
public Meat createMeat() {
return new FreshMeat();
}
@Override
public YuanLiao createYuanliao() {
return new LaWeiYuanLiao();
}
}
4.2 接下来修改肉夹馍生产接口,肉夹馍中的肉 ,调料都需要调用总店的原料。
package com.soup.redis.common;
import com.soup.redis.factory.RouJiaMoYLFactroy;
/**
* @Author tanghh
* @Date 2020/7/17 14:48
*/
public abstract class RouJiaMo {
public String name;
/**
* 准备工作
*
* @param ylFactroy
*/
public final void prepare(RouJiaMoYLFactroy ylFactroy) {
Meat meat = ylFactroy.createMeat();
YuanLiao yuanliao = ylFactroy.createYuanliao();
System.out.println("使用官方的原料" + meat.name + " , " + yuanliao.name + "作为原材料制作肉夹馍 ");
}
/**
* 使用你们的专用袋-包装
*/
public final void pack() {
System.out.println("肉夹馍-专用袋-包装");
}
/**
* 秘制设备-烘烤2分钟
*/
public final void fire() {
System.out.println("肉夹馍-专用设备-烘烤");
}
}
卖肉夹馍的店
package com.soup.redis.store;
import com.soup.redis.common.RouJiaMo;
/**
* @Author tanghh
* @Date 2020/7/17 15:52
*/
public abstract class RoujiaMoStore {
public abstract RouJiaMo createRouJiaMo(String type);
/**
* 根据传入类型卖不同的肉夹馍
*
* @param type
* @return
*/
public abstract RouJiaMo sellRouJiaMo(String type);
}
package com.soup.redis.store;
import com.soup.redis.common.*;
import com.soup.redis.factory.RouJiaMoYLFactroy;
/**
* @Author tanghh
* @Date 2020/7/17 15:52
*/
public class XianRouJiaMoStore extends RoujiaMoStore {
@Override
public RouJiaMo createRouJiaMo(String type)
{
RouJiaMo rouJiaMo = null;
if (type.equals("Suan"))
{
rouJiaMo = new XianSuanRouJiaMo();
} else if (type.equals("Tian"))
{
rouJiaMo = new XianTianRouJiaMo();
} else if (type.equals("La"))
{
rouJiaMo = new XianLaRouJiaMo();
}
return rouJiaMo;
}
@Override
public RouJiaMo sellRouJiaMo(String type) {
RouJiaMo rouJiaMo = createRouJiaMo(type);
RouJiaMoYLFactroy ylFactroy = new RouJiaMoYLFactroy() {
@Override
public Meat createMeat() {
return new FreshMeat();
}
@Override
public YuanLiao createYuanliao() {
return new LaWeiYuanLiao();
}
};
rouJiaMo.prepare(ylFactroy);
rouJiaMo.fire();
rouJiaMo.pack();
return rouJiaMo;
}
}
4.3 测试
package com.soup.redis.test;
import com.soup.redis.common.RouJiaMo;
import com.soup.redis.store.RoujiaMoStore;
import com.soup.redis.store.XianRouJiaMoStore;
/**
* @Author tanghh
* @Date 2020/7/17 14:58
*/
public class FactoryTest {
public static void main(String[] args) {
//西安分店卖肉夹馍
RoujiaMoStore roujiaMoStore = new XianRouJiaMoStore();
RouJiaMo suanRoujiaMo = roujiaMoStore.sellRouJiaMo("Suan");
System.out.println(suanRoujiaMo.name);
}
}
抽象方法模式到这就结束了,
最后这部分补充一下代码
package com.soup.redis.common;
/**
* @Author tanghh
* @Date 2020/7/17 15:46
*/
public abstract class Meat {
protected String name;
}
package com.soup.redis.common;
/**
* @Author tanghh
* @Date 2020/7/17 15:47
*/
public class FreshMeat extends Meat {
public FreshMeat(){
this.name = "新鲜的肉";
}
}
package com.soup.redis.common;
/**
* @Author tanghh
* @Date 2020/7/17 15:46
*/
public abstract class YuanLiao {
protected String name;
}
package com.soup.redis.common;
/**
* @Author tanghh
* @Date 2020/7/17 15:47
*/
public class LaWeiYuanLiao extends YuanLiao{
public LaWeiYuanLiao(){
this.name = "辣味原料";
}
}