Java_你应该知道的26种设计模式

时间:2022-04-17 20:26:57

四。 模板方法模式

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. &lbrack;译&rsqb;你应该知道的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&num; 语言历史版本特性(C&num; 1&period;0到C&num; 8&period;0汇总) SQL Server事务 事务日志 SQL Server 锁详解 软件架构之 23种设计模式 Oracle与Sqlserver:Order by NULL值介绍 asp&period;net MVC漏油配置总结

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

  7. 关于C&num;你应该知道的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种设计模式&lpar;转&rpar;

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

随机推荐

  1. laravel5&period;2,注册服务提供者时无法生效

    laravel中注册服务提供者原本很简单,只要运行下指令php artisan make:provider TestServiceProvider,然后在config/app.php的provider ...

  2. Python:常用函数封装

    def is_chinese(uchar): """判断一个unicode是否是汉字""" if uchar >= u'\u4e00' ...

  3. shell 常用命令

    Terminal是Mac OS X系统中的字符控制界面,可以更灵活地控制苹果电脑以下看到 “>“ 就是打指令的地方,prompt,指令列>pwd列出路径>ls列出此档案夹里所有的东西 ...

  4. zoj 3557 How Many Sets II

    How Many Sets II Time Limit: 2 Seconds      Memory Limit: 65536 KB Given a set S = {1, 2, ..., n}, n ...

  5. RGB颜色对照图

  6. Bootstrap 基本用法(续)

    在bootstrap中有很多的组件,这些组件可以帮组我们更快的写出一些好看的样式,下面就是一些样式: 导航框: <ul class="nav nav-tabs"> &l ...

  7. 浅谈Javascript闭包

    垃圾回收器 我个人把闭包抽象的称之为”阻止垃圾回收器的函数”或者”有权访问另一个函数内部变量的函数"(当然这个是我个人的理解方式,每个人可能会有不同的理解方式),为什么这样说?这样说还得说说 ...

  8. 做了个新的UWP类库 Sharp2D

    C#开发UWP的时候如果要实现高斯模糊效果的话,最好的选择似乎是微软的Win2D 但是Win2D太过庞大了,仅仅是庞大其实也没啥问题,毕竟net core就很庞大,但Win2d是一个Winmd组件 w ...

  9. js算法集合(一) 水仙花数 及拓展(自幂数的判断)

    js算法集合(一) ★ 最近有些朋友跟我说对js中的一些算法感到很迷惑,知道这个算法到底是怎么回事,但是就是不会用代码把它写出来,这里我跟大家分享一下做水仙花数的算法的思路,并对其扩展到自幂数的算法, ...

  10. HTML笔记&lt&semi;note2&gt&semi;

    文本标记 我是正常的文本段落 我是用b标记的加粗文本 我是用strong定义的强调文本 i标记的倾斜文本 em强调文本 del标记的删除线 del标记的下划线文本 特殊字符标记 显示 说明 空格&am ...