模板方法模式: 定义一个操作中的算法骨架(父类),而将一些步骤延迟到子类。模板方法使得子类可以不改变一个算法的结构来重定义该算法的。
实现一些操作时,整体步骤很固定,但是呢,就是其中一小部分需要改变,这时候可以使用模板方法模式,将容易变的部分抽象出来,供子类实现。
其实很多框架中都有用到了模板方法模式。例如: 数据库访问的封装、Junit 单元测试、servlet 中关于 doGet/doPost 方法的调用等等。
例如:
去餐厅吃饭,餐厅给我们提供了一个模板就是: 看菜单,点菜,吃饭,付款走人 (这里 “点菜和付款” 是不确定的由子类来完成的,其他的则是一个模板。
先定义一个模板,把模板中的点菜和付款,让子类来实现。
package com.lijie;
//模板方法
public abstract class RestaurantTemplate{
// 1.看菜单
public void menu(){
System.out.println("看菜单");
}
// 2.点菜业务
abstract void spotMenu();
// 3.吃饭业务
public void havingDinner(){
System.out.println("饭");
}
// 3.付款业务
abstract void payment();
//4.走人
public void GoR(){
System.out.println("走人");
}
//模板通用结构
public void process(){
menu();
spotMenu();
havingDinner();
payment();
GoR();
}
}
具体的模板方法子类 1
package com.lijie;
public class RestaurantGinsengImpl extends RestaurantTemplate{
void spotMenu(){
System.out.println("人参");
}
void payment(){
System.out.println("5 快");
}
}
具体的模板方法子类 2
package com.lijie;
public class RestaurantLobsterImpl extends RestaurantTemplate{
void spotMenu(){
System.out.println("龙虾");
}
void payment(){
System.out.println("50块");
}
}
1、客户端测试
package com.lijie;
public class Client{
public static void main(String[] args) {
//调用第一个模板实例
RestaurantTemplate restaurantTemplate = new RestaurantGinsengImpl();
restaurantTemplate.process();
}
}
外观模式:也叫门面模式,隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。
它向现有的系统添加一个接口,用这一个接口来隐藏实际的系统的复杂性使用外观模式,他外部看起来就是一个接口,其实他的内部有很多复杂的接口已经被实现
用户注册完之后,需要调用阿里短信接口、邮件接口、微信推送接口。
创建阿里短信接口
package com.lijie;
//阿里短信消息
public interface AliSmsService{
void sendSms();
}
package com.lijie;
public class AliSmsServiceImpl implements AliSmsService{
public void sendSms(){
System.out.println("阿里短信消息");
}
}
1、创建邮件接口
package com.lijie;
//发送邮件消息
public interface EamilSmsService{
void sendSms();
}
package com.lijie;
public class EamilSmsServiceImpl implements EamilSmsService{
public void sendSms(){
System.out.println(发送邮件消息");
}
}
创建微信推送接口
package com.lijie;
//微信消息推送
public interface WeiXinSmsService(){
void sendSms();
}
package com.lijie;
public class WeiXinSmsServiceImpl implements WeiXinSmsService{
public void sendSms(){
System.out.println("发送微信消息推送");
}
}
创建门面 (门面看起来很简单使用,复杂的东西以及被门面给封装好了)
package com.lijie;
public class Computer {
AliSmsService aliSmsService;
EamilSmsService eamilSmsService;
WeiXinSmsService weiXinSmsService;
public Computer(){
aliSmsService = new AliSmsServiceImpl();
eamilSmsService = new EamilSmsServiceImpl();
weiXinSmsService = new WeiXinSmsServiceImpl();
}
//只需要调用它
public void sendMs(){
aliSmsService.sendSms();
eamilSmsService.sendSms();
weiXinSmsService.sendSms();
}
}
启动测试
package com.lijie;
public class Client{
public static void main(String[] args){
//普通模式需要这样
AliSmsService aliSmsService = new AliSmsServiceImpl();
EamilSmsService eamilSmsService = new EamilSmsServiceImpl();
WeiXinSmsService weiXinSmsService = newWeiXinSmsServiceImpl();
aliSmsService.sendSms();
eamilSmsService.sendSms();
weiXinSmsService.sendSms();
//利用外观模式简化方法
new Computer().sendMsg();
}
}
原型设计模式简单来说就是克降原型表明了有一个样板实例,这个原型是可定制的。原型模式多用于创建复杂的或者构造耗时的实例,因为这种情况下,复制一个已经存在的实例可使程序运行更高效。
我们 Spring 框架中的多例就是使用原型
创建 User 类
package com.lijie;
import java.util.ArrayList;
public class User implements Cloneable{
private String name;
private String password;
private ArrayList phones;
protected User clone(){
try (
User user = (User) super.clone();
//重点,如果要连带引用类型一起复制,需要添加底下一条代码,如果不加就对于是复制了引用地址
user.phones =(ArrayList) this.phones.clone();//设置深复制
return user;
}catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
//省略所有属性 Git Set 方法.....
}
测试复制
package com.lijie;
import java.util.ArrayList;
public class Client{
public static void main(String[] args){
//创建 User 原型对象
User user = new User();
user.setName("李三");
user.setPassword("123456");
ArrayList phones = new ArrayList<>();
phones.add("17674553302");
user.setPhones(phones);
//copy 一个 user 对象并且对象的属性
User user2 = user.clone();
user2.setPassword("654321");
//查看俩个对象是否是一个
System.out.println(user == user2);
//查看属性内容
System.out.println(user.getName() + "|" + user2.getName());
System.out.println(user.getPassword() + "|" + user2.getPassword());
//查看对于引用类型拷贝
System.out.println(user.getPhones() == user2.getPhones());
}
}
如果不需要深复制,需要删除 User 中的
//默认引用类型为浅复制,这是设置了深复制
user.phones = (ArrayList) this.phones.clone();