23种设计模式
- 单例(Singleton)模式: 某个类只能生成一个实例,该类提供了一个全局访问点供外部获取该实例,其拓展是有限多例模式。
- 原型(Prototype)模式: 将一个对象作为原型,通过对其进行复制而克隆出多个和原型类似的新实例。
- 工厂方法(Factory Method)模式: 定义一个用于创建产品的接口,由子类决定生产什么产品。
简单工厂模式: 不满足开闭原则 , 生产东西固定,如需添加,必须修改代码
/**
* 简单工厂,只能生产宠物狗和宠物猫两个实例
*/
public class PetStore {
private static final String DOG = "dog" ;
private static final String CAT = "cat" ;
/*方法一*/
public static Pet getPet(String pet){
if (DOG.equals(pet)){
return new Dog();
} else if (CAT.equals(pet)){
return new Cat();
} else {
return null ;
}
}
/*方法二*/
public static Pet getDog(){
return new Dog();
}
public static Pet getCat(){
return new Cat();
}
}
工厂方法模式: 定义抽象工厂统一接口, 让子工厂生产, 然后通过子工厂获得实例对象,缺点是要知道子类工厂的名字(可以通过xml文件获取名字,然后利用反射获取子工厂,但是简单工厂模式也可以)
public interface PetStore {
/*获取宠物实例 */
Pet get();
}
public class DogStore implements PetStore {
/*获取宠物狗实例*/
public Pet get() {
return new Dog();
}
}
public class CatStore implements PetStore {
/* 获取宠物猫实例*/
public Pet get() {
return new Cat();
}
}
public class Consumer {
public static void main(String[] args) {
//通过宠物狗专卖店得到狗狗
Pet pet = new DogStore().get();
pet.say();
}
}
- 抽象工厂(Abstract Factory)模式: 提供一个创建产品族的接口,其每个子类可以生产一系列相关的产品。
抽象工厂模式是对工厂模式的延伸,工厂模式主要是生产一种类型产品的工厂; 抽象工厂是能实现多种类型产品的工厂,通过抽象工厂接口定义不同的方法,使得具体工厂能够生产系列产品
//抽象工厂接口,生产两种产品:手机 , 路由器
public interface StoreFactory {
//获取手机产品实例
PhoneProduct getPhone();
// 获取路由产品实例
RouterProduct getRouter();
}
/*产品接口一:手机产品接口*/
public interface PhoneProduct {
// 开机
void start();
//关机
void shutdown();
//发短信
void sendMsg();
}
/*产品接口二:手机产品接口*/
public interface RouterProduct {
//开机
void start();
//关机
void shutdown();
//发送信号
void sendWifi();
}
/*子类工厂一: 华为工厂*/
public class HuaweiFactory implements StoreFactory {
// 获取手机产品实例
@Override
public PhoneProduct getPhone() {
return new HuaweiPhone();
}
//获取路由产品实例
@Override
public RouterProduct getRouter() {
return new HuaweiRouter();
}
}
/*子类工厂二:小米工厂*/
public class XiaomiFactory implements StoreFactory {
//获取手机产品实例
@Override
public PhoneProduct getPhone() {
return new XiaomiPhone();
}
// 获取路由产品实例
@Override
public RouterProduct getRouter() {
return new XiaomiRouter();
}
}
- 建造者(Builder)模式: 将一个复杂对象分解成多个相对简单的部分,然后根据不同需要分别创建它们,最后构建成该复杂对象。
将对象的属性的赋值的具体操作分离出来,即用户通过建造者创建产品对象,建造者在创建产品对象的时候进行赋值,用户也能通过建造者封装好的操作对产品DIY
好处是: 可以将复杂的赋值过程分离出来,交给其他工作者来实现属性的赋值; 用户只需要找对应的工作者进行自定义赋值, 甚至直接找设计者拿取成型产品
/*抽象建造者定义建造方法*/
public abstract class Builder {
protected Product product = new Product();
abstract void buildA(); //装发动机
abstract void buildB(); //装车牌
abstract void buildC(); //装车轮
abstract Product getProduct();
}
/*具体工作者负责操作实现*/
public class Worker extends Builder {
@Override
void buildA() {
product.setPartA("发动机");
System.out.println("安装发动机");
}
@Override
void buildB() {
product.setPartB("车牌");
System.out.println("安装车牌");
}
@Override
void buildC() {
product.setPartC("车轮");
System.out.println("安装车轮");
}
//获取产品
@Override
Product getProduct() {return product;}
}
/*具体产品*/
public class Product {
private String partA ; //发动机
private String partB ; //车牌
private String partC ; //车轮
@Override
public String toString() {
return "Product{" +
"partA='" + partA + '\'' +
", partB='" + partB + '\'' +
", partC='" + partC + '\'' +
'}';
}
}
/*设计者负责操作装配(此处也可以消费者自行DIY)*/
public class Director {
// 设计者负责装配顺序
public Product builder(Builder builder){
builder.buildA();
builder.buildB();
builder.buildC();
return builder.getProduct();
}
}
- 代理(Proxy)模式: 为某对象提供一种代理以控制对该对象的访问。即客户端通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。
静态代理模式: 通过实现统一主题接口, 代理者对真实主题进行补充优化
优点: 不用修改原代码
缺点: 每个真实角色都会产生一个代理角色, 当主题只能有一个,如果主题内方法过多,需要重复写代理过程
/*抽象主题接口,定义房屋出租主题*/
public interface Rent {
void rent();//房屋出租
}
/*房屋主人实现接口,实现出租具体行为*/
public class Host implements Rent {
@Override
public void rent() {
System.out.println("出租A单元303号房");
}
}
/*代理者,对真实行为做补充*/
public class Proxy implements Rent {
private Host host ;
public Proxy() {
this.host = new Host();
System.out.println("中介寻找房源");
}
@Override
public void rent() {
checkHouse();
seeHouse();
host.rent();
System.out.println("你住了6个月,不住了");
checkHouse();
checkOutHouse();
}
public void seeHouse(){
System.out.println("中介带你看房子");
}
public void checkHouse(){
System.out.println("中介查验房子");
}
public void checkOutHouse(){
System.out.println("中介帮你退房");
}
}
动态代理模式
动态代理主要分为两大类: 基于接口的动态代理,基于类的动态代理
- 基于接口 – JDK 动态代理
- 基于类 : cglib
- java字节码实现 – javasist(主要用于tomcat)
/*JDK动态代理*/
/*通过这个类动态生成代理*/
public class ProxyInvocationHandler implements InvocationHandler {
// 被代理的接口(随便给)
private Object target ;
public void setTarget(Object target) {
this.target = target;
}
/**
* 可以用 lombok 实现接口 InvocationHandler
* @return
*/
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
target.getClass().getInterfaces() ,this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
log(method.getName());
Object result = method.invoke(target,args);
return result;
}
//打印日志信息
void log(String msg){
System.out.println("执行了"+msg+"方法");
}
}
/*随便给一个接口*/
public interface UserService {
void add();
void delete();
void insert();
void select();
}
/*该接口的真实实现者*/
public class UserServiceImpl implements UserService {
@Override
public void add() {
System.out.println("添加用户");
}
@Override
public void delete() {
System.out.println("删除用户");
}
@Override
public void insert() {
System.out.println("修改用户");
}
@Override
public void select() {
System.out.println("查询用户");
}
}
/*测试*/
public class Test {
public static void main(String[] args) {
UserServiceImpl userService = new UserServiceImpl();
ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();
proxyInvocationHandler.setTarget(userService);
UserService proxy = (UserService) proxyInvocationHandler.getProxy();
proxy.add();
proxy.delete();
proxy.insert();
proxy.select();
}
}
/*测试结果*/
执行了add方法
添加用户
执行了delete方法
删除用户
执行了insert方法
修改用户
执行了select方法
查询用户
- 适配器(Adapter)模式: 将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。
- 桥接(Bridge)模式: 将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。
- 装饰(Decorator)模式: 动态的给对象增加一些职责,即增加其额外的功能。
- 外观(Facade)模式: 为多个复杂的子系统提供一个一致的接口,使这些子系统更加容易被访问。
- 享元(Flyweight)模式: 运用共享技术来有效地支持大量细粒度对象的复用。
- 组合(Composite)模式: 将对象组合成树状层次结构,使用户对单个对象和组合对象具有一致的访问性。
- 模板方法(Template Method)模式: 定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。
- 策略(Strategy)模式: 定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的改变不会影响使用算法的客户。
- 命令(Command)模式: 将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。
- 职责链(Chain of Responsibility)模式: 把请求从链中的一个对象传到下一个对象,直到请求被响应为止。通过这种方式去除对象之间的耦合。
- 状态(State)模式: 允许一个对象在其内部状态发生改变时改变其行为能力。
- 观察者(Observer)模式: 多个对象间存在一对多关系,当一个对象发生改变时,把这种改变通知给其他多个对象,从而影响其他对象的行为。
- 中介者(Mediator)模式: 定义一个中介对象来简化原有对象之间的交互关系,降低系统中对象间的耦合度,使原有对象之间不必相互了解。
- 迭代器(Iterator)模式: 提供一种方法来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。
- 访问者(Visitor)模式: 在不改变集合元素的前提下,为一个集合中的每个元素提供多种访问方式,即每个元素有多个访问者对象访问。
- 备忘录(Memento)模式: 在不破坏封装性的前提下,获取并保存一个对象的内部状态,以便以后恢复它。
- 解释器(Interpreter)模式: 提供如何定义语言的文法,以及对语言句子的解释方法,即解释器。