四。 模板方法模式

Definition: Define the skeleton of an algorithm in an operation, deferring some steps to subclasses.

Templet Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.

它包含一个抽象模板和一些具体的模板。

抽象模板中包含两类方法:

  • 基本方法

    • 也叫基本操作,是有抽象模板给出抽象接口,子类给出实现的方法,并且这些方法会在模板方法中被调用;
    • 基本方法尽量设计为protected类型,符合迪米特法则
  • 模板方法
    • 可以有一个或几个,一般是一个具体方法,实现对基本方法的调度,完成固定的逻辑。
    • 为了防止恶意的操作,,一般模板方法都会加上final关键字,不允许被覆写。

Demo Coding:

package com.model;

public abstract class HummerModel {
/**
* 首先,这个模型要能发动起来,不管是电力发动还是手摇发动
* 所以具体是怎么发动就要根据不同的型号自己实现发动的方法
*/
public abstract void start(); /**
* 不仅能够发动,还要能够停止
*/
public abstract void stop(); /**
* 按喇叭会响
*/
public abstract void alarm(); /**
* 发动引擎时有隆隆声
*/
public abstract void engineBoom(); public void run() {
this.start();
this.engineBoom();
this.alarm();
this.stop();
}
} package com.model; public class HummerH1Model extends HummerModel { @Override
public void start() {
// TODO Auto-generated method stub
System.out.println("H1型号是这样启动的.....");
} @Override
public void stop() {
// TODO Auto-generated method stub
System.out.println("H1型号是这样停止的.....");
} @Override
public void alarm() {
// TODO Auto-generated method stub
System.out.println("H1型号是这样鸣笛的......");
} @Override
public void engineBoom() {
// TODO Auto-generated method stub
System.out.println("H1型号是这样发动引擎的......");
} } package com.model; public class HummerH2Model extends HummerModel { @Override
public void start() {
// TODO Auto-generated method stub
System.out.println("H2型号是这样启动的......");
} @Override
public void stop() {
// TODO Auto-generated method stub
System.out.println("H2型号是这样停止的......");
} @Override
public void alarm() {
// TODO Auto-generated method stub
System.out.println("H2型号是这样鸣笛的......");
} @Override
public void engineBoom() {
// TODO Auto-generated method stub
System.out.println("H2型号是这样发动引擎的......");
} } package com.model; public class Client { public static void main(String[] args) {
// TODO Auto-generated method stub
//某公司要H1模型的悍马汽车
HummerModel hm = new HummerH1Model();
//H1模型演示如下
hm.run();
} }

五。 建造者模式(Builder Pattern)

Definition: Separate the construction of a complex object from its representation so that the same

construction process can create different representations.

在一般的建造者模式中,有如下4个角色:

  • 产品类(实际就是上面的第四种模板方法模式的实现)

    • 通常是实现了模板方法模式,也就是有模板方法和基本方法;
  • 抽象建造者Builder
    • 规范产品的组建,一般由子类实现。
  • 具体构建着ConcreteBuilder
    • 实现抽象建造者的所有方法,并且返回一个组建好的对象
  • 导演类
    • 负责根据客户的需要安排已有模块的顺序,然后告诉Builder开始建造,然后获得ConcreteBuilder返回的对象,最后呈现给客户

所以说,不论是经由模板模式构建的产品类还是抽象或具体的建造者,对于客户都是屏蔽的,客户只需要将他的具体需求告诉导演类,最终由导演类统筹安排,将结果返回给客户。

建造者模式的使用场景有:

  • 如果需求是:相同的方法,不同的执行顺序,产生不同的事件结果时,可以考虑使用。
  • 一个对象由多个零件或部件构成,,但是运行产生的结果又不相同;
  • 所以,,建造者模式关注的是零件类型装配顺序不同!!!这是他与工厂方法最大的不同!!
  • 工厂模式的重点则是创建,创建零件的它的主要职责,组装顺序是它不care的!!

Demo Coding:

/*-------------------------模板方法模式的实现-----------------------------*/
package com.builderPattern; import java.util.ArrayList; public abstract class CarModel {
//这个参数是各个基本方法执行的顺序
private ArrayList<String> sequence = new ArrayList<String>(); protected abstract void start(); protected abstract void stop(); protected abstract void alarm(); protected abstract void engineBoom(); final public void run() {
//循环一遍sequence,谁在前就限制性谁
for(int i=0; i<this.sequence.size(); i++) {
String actionName = this.sequence.get(i);
if(actionName.equalsIgnoreCase("start"))
this.start();
else if(actionName.equalsIgnoreCase("stop"))
this.stop();
else if(actionName.equalsIgnoreCase("alarm"))
this.alarm();
else if(actionName.equalsIgnoreCase("engine boom"))
this.engineBoom();
}
} final public void setSequence(ArrayList<String> sequence) {
this.sequence = sequence;
} } package com.builderPattern; public class BenzModel extends CarModel { @Override
protected void start() {
// TODO Auto-generated method stub
System.out.println("奔驰是这样run....");
} @Override
protected void stop() {
// TODO Auto-generated method stub
System.out.println("奔驰是这样stop....");
} @Override
protected void alarm() {
// TODO Auto-generated method stub
System.out.println("奔驰是这样alarm....");
} @Override
protected void engineBoom() {
// TODO Auto-generated method stub
System.out.println("奔驰是这样engine boom.....");
} } package com.builderPattern; public class BMWModel extends CarModel { @Override
protected void start() {
// TODO Auto-generated method stub
System.out.println("宝马是这样start....");
} @Override
protected void stop() {
// TODO Auto-generated method stub
System.out.println("宝马是这样stop....");
} @Override
protected void alarm() {
// TODO Auto-generated method stub
System.out.println("宝马是这样alarm....");
} @Override
protected void engineBoom() {
// TODO Auto-generated method stub
System.out.println("宝马是这样engine boom....");
} } /*-------------------------抽象建造者-----------------------------*/
package com.builderPattern; import java.util.ArrayList; public abstract class CarBuilder {
//建造一个模型,你要给我一个顺序,就是组装顺序
public abstract void setSequence(ArrayList<String> sequence); //设置完顺序后,既可以直接拿到这个车辆模型
public abstract CarModel getCarModel();
} /*--------------具体建造者的实现,返回一个具体的model------------------------*/
package com.builderPattern; import java.util.ArrayList; public class BenzBuilder extends CarBuilder {
private BenzModel benz = new BenzModel(); @Override
public void setSequence(ArrayList<String> sequence) {
// TODO Auto-generated method stub
this.benz.setSequence(sequence);
} @Override
public CarModel getCarModel() {
// TODO Auto-generated method stub
return this.benz;
} } package com.builderPattern; import java.util.ArrayList; public class BMWBuilder extends CarBuilder {
private BMWModel bmw = new BMWModel(); @Override
public void setSequence(ArrayList<String> sequence) {
// TODO Auto-generated method stub
this.bmw.setSequence(sequence);
} @Override
public CarModel getCarModel() {
// TODO Auto-generated method stub
return this.bmw;
} } /*-------------------------导演类的实现,实现客户的需求-------------------------*/
package com.builderPattern; import java.util.ArrayList; public class Director {
private ArrayList<String> sequence = new ArrayList<String>();
private BenzBuilder benzBuilder = new BenzBuilder();
private BMWBuilder bmwBuilder = new BMWBuilder(); /**
* 获得A类型的奔驰汽车
* @return
*/
public BenzModel getABenzModel() {
this.sequence.clear(); this.sequence.add("start");
this.sequence.add("stop");
this.benzBuilder.setSequence(sequence);
return (BenzModel) this.benzBuilder.getCarModel();
} /**
* 获得B类型的奔驰汽车
* @return
*/
public BenzModel getBBenzModel() {
this.sequence.clear(); this.sequence.add("engine boom");
this.sequence.add("start");
this.sequence.add("stop");
this.benzBuilder.setSequence(sequence);
return (BenzModel) this.benzBuilder.getCarModel();
} /**
* 获得A类型的宝马车型
* @return
*/
public BMWModel getABMWModel() {
this.sequence.clear(); this.sequence.add("alarm");
this.sequence.add("start");
this.sequence.add("stop"); this.bmwBuilder.setSequence(sequence);
return (BMWModel) this.bmwBuilder.getCarModel(); } /**
* 获得B类型的宝马车型
* @return
*/
public BMWModel getBBMWModel() {
this.sequence.clear(); this.sequence.add("start"); this.bmwBuilder.setSequence(sequence);
return (BMWModel) this.bmwBuilder.getCarModel(); } } package com.builderPattern; public class Client { public static void main(String[] args) {
// TODO Auto-generated method stub
Director director = new Director();
//制造100台A类型的奔驰
for(int i=0; i<1000; i++)
director.getABenzModel().run();
for(int i=0; i<2000; i++)
director.getBBMWModel().run();
} }

六。代理模式(Proxy Pattern)

Definition: Provide a surrogate or placeholder for another object to control access to it.

在代理模式中,有三个角色的定义:

  • Subject抽象主题角色

    • 抽象主题可以是抽象类也可以是接口,是一个最普通的业务类型定义;
  • RealSubject具体主题角色
    • 也叫作被委托角色。是具体业务逻辑的具体执行者;
  • Proxy代理主题角色
    • 也叫委托类、代理类,它负责对真实角色的应用,把所有抽象主题类定义的方法委托给真实主题角色实现,并且在真实主题角色处理完毕后做预处理和善后工作;
  • RealSubject 和 Proxy都继承自Subject

Demo Coding:

package com.proxyPattern;

public interface IGamePlayer {
//玩家登陆
public void login(String name, String password); //打boss
public void killBoss(); //升级
public void upgrade(); } package com.proxyPattern; public class GamePlayer implements IGamePlayer {
private String name = ""; public GamePlayer(String name) {
this.name = name;
} @Override
public void login(String name, String password) {
// TODO Auto-generated method stub
System.out.println("Congradulation! " + this.name + " logined in.");
} @Override
public void killBoss() {
// TODO Auto-generated method stub
System.out.println(this.name + " is killing his boss..");
} @Override
public void upgrade() {
// TODO Auto-generated method stub
System.out.println(this.name + " uograded 1.");
} } package com.proxyPattern; public class GamePlayerProxy implements IGamePlayer {
IGamePlayer gamePlayer = null; public GamePlayerProxy(IGamePlayer gamePlayer) {
this.gamePlayer = gamePlayer;
} @Override
public void login(String name, String password) {
// TODO Auto-generated method stub
this.gamePlayer.login(name, password);
} @Override
public void killBoss() {
// TODO Auto-generated method stub
this.gamePlayer.killBoss();
} @Override
public void upgrade() {
// TODO Auto-generated method stub
this.gamePlayer.upgrade();
} } package com.proxyPattern; public class Client { public static void main(String[] args) {
// TODO Auto-generated method stub
IGamePlayer gamePlayer = new GamePlayer("Tom");
IGamePlayer proxy = new GamePlayerProxy(gamePlayer);
proxy.login("Tom", "123");
proxy.killBoss();
proxy.upgrade(); //Another player
IGamePlayer gamePlayer2 = new GamePlayer("Jack");
IGamePlayer proxy2 = new GamePlayerProxy(gamePlayer2);
proxy2.login("Jack", "456");
proxy2.killBoss();
proxy2.upgrade(); } }

代理模式的扩展:

(一)普通代理

  • 要求客户端只能访问代理角色,而不能访问真实角色

(二)强制代理

  • 不管是通过代理类还是通过直接new一个主题角色类,都不能访问,只有通过真实角色指定的代理类才可以访问
  • Demo Coding:
  • package com.forceProxyPattern;
    
    public interface IGamePlayer {
    //玩家登陆
    public void login(String name, String password); //打boss
    public void killBoss(); //升级
    public void upgrade(); //每个人都有自己的代理
    public IGamePlayer getProxy();
    } package com.forceProxyPattern; public class GamePlayer implements IGamePlayer {
    private String name = "";
    //我的代理
    private IGamePlayer proxy = null; public GamePlayer(String name) {
    this.name = name;
    } @Override
    public void login(String name, String password) {
    // TODO Auto-generated method stub
    if(this.isProxy()) {
    System.out.println(this.name + " 登陆成功!");
    } else {
    System.out.println("请使用指定的代理访问");
    }
    } @Override
    public void killBoss() {
    // TODO Auto-generated method stub
    if(this.isProxy()) {
    System.out.println(this.name + " 在打怪。");
    } else {
    System.out.println("请使用指定的代理访问");
    }
    } private boolean isProxy() {
    // TODO Auto-generated method stub
    if(proxy == null)
    return false;
    else
    return true;
    } @Override
    public void upgrade() {
    // TODO Auto-generated method stub
    if(this.isProxy()) {
    System.out.println(this.name + " 又升一级!");
    } else {
    System.out.println("请使用指定的代理访问");
    }
    } //找到自己的代理
    @Override
    public IGamePlayer getProxy() {
    // TODO Auto-generated method stub
    this.proxy = new GamePlayerProxy(this);
    return this.proxy;
    } } package com.forceProxyPattern; public class GamePlayerProxy implements IGamePlayer {
    private IGamePlayer gamePlayer = null; public GamePlayerProxy(IGamePlayer gamePlayer) {
    this.gamePlayer = gamePlayer;
    } @Override
    public void login(String name, String password) {
    // TODO Auto-generated method stub
    this.gamePlayer.login(name, password);
    } @Override
    public void killBoss() {
    // TODO Auto-generated method stub
    this.gamePlayer.killBoss();
    } @Override
    public void upgrade() {
    // TODO Auto-generated method stub
    this.gamePlayer.upgrade();
    } @Override
    public IGamePlayer getProxy() {
    // TODO Auto-generated method stub
    return this;
    } } package com.forceProxyPattern; public class Client { public static void main(String[] args) {
    // TODO Auto-generated method stub
    //定义一个游戏的角色
    IGamePlayer player = new GamePlayer("李四");
    //获得指定代理
    IGamePlayer proxy = player.getProxy();
    proxy.login("lisi", "123");
    proxy.killBoss();
    proxy.upgrade();
    } }

(三)动态代理

  • 动态代理在实现阶段不关心代理谁,而在运行阶段才指定代理哪一个对象;
  • 一个非常流行的编程方式叫做面向横切面编程(Aspect Oriented Programming-AOP),其核心就是采用了动态代理机制。
  • Demo Coding:
  • public interface Subject {
    //业务操作
    public void doSomething(String str);
    } public class RealSubject implements Subject {
    //具体的业务操作实现
    public void doSomething(String str) {
    System.out.println("do something..");
    }
    } //动态代理的Handler类
    public class MyInvocationHandler implements InvocationHandler {
    //被代理的对象
    private Object target = null;
    //通过构造函数传递一个对象
    public MyInvocationHandler(Object target) {
    this.target = target;
    } //代理方法
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    //执行被代理的方法
    return method.invoke(this.target, args);
    } } public class Client { public static void main(String[] args) {
    // // TODO Auto-generated method stub
    //定义一个主题
    Subject subject = new RealSubject();
    //定义一个Handler
    InvocationHandler handler = new MyInvocationHandler(subject);
    //获得类的class loader
    ClassLoader cl = subject.getClass().getClassLoader();
    //动态产生一个代理者
    Subject proxy = (Subject) Proxy.newProxyInstance(cl, new Class[]{Subject.class}, handler); proxy.doSomething("Finish"); } }

六。原型模式(Prototype Pattern)

Definition: Specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype.

  • 原型模式的核心是一个clone方法,通过该方法进行对象的拷贝,java提供了一个Cloneable接口来标识这个对象是可以拷贝的,JVM中只有这个标记的对象才有可能被拷贝;
  • 原型模式通用代码:
    • public class PrototypeClass implements Cloneable {
      //覆写父类中的方法 @Override
      public PrototypeClass clone() {
      PrototypeClass prototypeClass = null;
      try {
      prototypeClass = (PrototypeClass) super.clone();
      } catch(CloneNotSupportedException e) {
      e.printStackTrace();
      }
      return prototypeClass;
      }
      }
  • 优点:
    • 原型模式是在内存二进制流的拷贝,比直接new一个对象性能好很多,特别是在一个循环体内产生大量对象的时候;
    • 逃避构造函数的约束:直接在内存中拷贝,构造函数是不会被执行的。
  • 使用场景:
    • 资源优化场景:类初始化需要非常多的资源,包括数据、硬件资源等;
    • 性能和安全要求的场景:用过new产生一个对象需要非常繁琐的数据准备货访问权限,则可以使用原型模式;
    • 一个对象多个修改者的场景:一个对象需要提供给其他对象访问,而且各个调用者可能需要修改其值时。
    • 在实际的项目中,原型模式一般与工厂模式一起出现,用过clone方法创建一个对象,然后由工厂方法提供给调用者。
  • 深拷贝与浅拷贝:
    • 浅拷贝:Object类提供的方法clone只是拷贝本对象,其对象内部的数组、引用对象等都不拷贝,还是指向原声对象的呢哦不元素地址。(即拷贝的仅仅是内部对象的地址)
    • 深拷贝:拷贝的是对象本身
    • 二者分开使用
  • final与clone的相爱相杀:若想使用clone,就不要加final关键字了。

    

(-------------------未完待续----------------------)

Java_你应该知道的26种设计模式的更多相关文章

  1. 每个IT安全专业人员应该知道的12种根本漏洞

    每个IT安全专业人员应该知道的12种根本漏洞 每年,IT安全专业人员都面临着数千个新的软件漏洞和数百万个不同的恶意软件程序,但只有12种根本漏洞会让这些软件漏洞和恶意软件程序攻击你的设备.了解这些根本 ...

  2. [译]你应该知道的4种JavaScript设计模式

    这里介绍下面这4种设计模式 Module Prototype Observer Singleton 每种模式有许多属性构成,在这我只强调一下几点: 1 Context: 在何种情况使用哪种模式? 2 ...

  3. 新手指南: Linux 新手应该知道的 26 个命令

    当你进入了 Linux 的世界,在下载.安装 了某个 Linux 发行版,体验了 Linux 桌面并安装了一些你喜爱和需要的软件之后,应该去了解下 Linux 真正的魅力所在:命令行.每一个 Linu ...

  4. Linux 新手应该知道的 26 个命令

    https://linux.cn/article-6160-1.html 当你进入了 Linux 的世界,在下载.安装 了某个 Linux 发行版,体验了 Linux 桌面并安装了一些你喜爱和需要的软 ...

  5. 你需要知道的 N 种抓取 dump 的工具

    原总结注册表debug调试dump转储文件windbgprocdump 前言 今天,向大家介绍几种可以抓取应用程序转储文件的工具及基本使用方法.更详细的用法,请参考每个工具对应的帮助文档.如果你还不清 ...

  6. 为什么说JAVA中要慎重使用继承 C# 语言历史版本特性(C# 1.0到C# 8.0汇总) SQL Server事务 事务日志 SQL Server 锁详解 软件架构之 23种设计模式 Oracle与Sqlserver:Order by NULL值介绍 asp.net MVC漏油配置总结

    为什么说JAVA中要慎重使用继承   这篇文章的主题并非鼓励不使用继承,而是仅从使用继承带来的问题出发,讨论继承机制不太好的地方,从而在使用时慎重选择,避开可能遇到的坑. JAVA中使用到继承就会有两 ...

  7. 关于C#你应该知道的2000件事

    原文 关于C#你应该知道的2000件事 下面列出了迄今为止你应该了解的关于C#博客的2000件事的所有帖子. 帖子总数= 1,219 大会 #11 -检查IL使用程序Ildasm.exe d #179 ...

  8. 关于WPF你应该知道的2000件事

    原文 关于WPF你应该知道的2000件事 以下列出了迄今为止为WPF博客所知的2,000件事所创建的所有帖子. 帖子总数= 1,201 动画 #7 - 基于属性的动画 #686 - 使用动画制作图像脉 ...

  9. 从追MM谈Java的23种设计模式(转)

    从追MM谈Java的23种设计模式    这个是从某个文章转载过来的.但是忘了原文链接.如果知道的,我追加一下. 1.FACTORY-追MM少不了请吃饭了,麦当劳的鸡翅和肯德基的鸡翅都是MM爱吃的东西 ...

随机推荐

  1. jquery表单重置另一种方法

    页面中按钮为<a>标签时,点击取消按钮,表单内容重置,需要给form表单id="form": <a class="demo_one1" onc ...

  2. dota玩家与英雄契合度的计算器,python语言scrapy爬虫的使用

    首发:个人博客,更新&纠错&回复 演示地址在这里,代码在这里. 一个dota玩家与英雄契合度的计算器(查看效果),包括两部分代码: 1.python的scrapy爬虫,总体思路是pag ...

  3. 如何在图像处理工具包ImagXpress中对图像进行捕捉、复制和粘贴

    如何在在ImagXpress中进行图像的捕捉. 复制和粘贴呢?下面详细来看一下,在多种情况下,图和实现这些操作. 捕捉屏幕图像 捕捉通过ImageXView窗口绑定的屏幕范围,以及保存到一个Image ...

  4. PHPCMS V9 环境搭建

    PHPCMS V9的学习总结分为以下几点: [1]PHPCMS 简介 PHP原始为Personal Home Page的缩写,(外文名:PHP: Hypertext Preprocessor,中文名: ...

  5. shell 条件测试语句三种方法

    1.test -f file  2.[ -f file ] 3.[[ -f file ]] [ -f file1 -a -f file2]逻辑与[ -f file1 -o -f file2]逻辑或 [ ...

  6. JSP:一种服务器端动态页面技术的组件规范。

    java Servlet page:java服务器端页面,会增加服务器的压力. jsp文件会被容器转换成一个Servlet类然后执行. JSP页面中的注释: HTML注释:<!-- 注释中的ja ...

  7. 【python cookbook】【字符串与文本】11.从字符串中去掉不需要的字符

    问题:在字符串的开始.结尾或中间去掉不需要的字符,比如说空格符 解决方案: 1.字符串开始或结尾处去掉字符:str.strip() 2.从左或从右侧开始执行去除字符:str.lstrip().str. ...

  8. LCD参数解释及计算【转】

    转自:http://blog.csdn.net/longxiaowu/article/details/24319933 Linux内核的amba lcd控制器使用clcd_panel结构体表示一个LC ...

  9. 【Pro ASP.NET MVC 3 Framework】.学习笔记.2.MVC的主要工具-Ninject

    这三个工具,应该是每个MVC程序员的兵工厂中的一部分.DI容器,单元测试框架,mocking 工具.Ninject是我们偏爱的DI容器,它简单,高雅,并且容易使用.这里有很多复杂的替代品,但是我们喜欢 ...

  10. mongo VUE 操作

    一  修改字段名称 db.rc_配置_付款限额_消费.update({ "生效标识" : 1, "$atomic" : "true" },{ ...