设计模式
一、设计模式分类
创建型模式:对象实例化的模式,创建型模式用于解耦对象的实例化过程。
结构型模式:把类或对象结合在一起形成一个更大的结构。
行为型模式:类和对象如何交互,及划分责任和算法。
二、创建型模式
1、单例模式
public class SingletonDCL {
private volatile static SingletonDCL singletonDCL;
private SingletonDCL() {
}
public static SingletonDCL getInstance() {
if (null == singletonDCL) {
synchronized (SingletonDCL.class) {
if (null == singletonDCL) {
singletonDCL = new SingletonDCL();
}
}
}
return singletonDCL;
}
}
2、工厂模式
2.1、工厂模式的特点
控制对象的生产都可以称为工厂模式,其中包括简单工厂、抽象工厂
2.2、简单工厂模式
简单工厂只能生产单一品种的产品,例如活动检查的工厂只能生产活动检查的对象,可以生产购物类活动检查的对象也可以生产非购物类检查的对象;同样券检查的工厂只能生产券检查的对象,可以生产普通券检查的对象也可以生产运费券检查的对象;但是活动检查的工厂不能生产券检查的对象。因此简单工厂只能生产单一品种的产品,但同时如果需要扩展另一个品种也只需要添加一个另一品种的工厂即可,不会牵涉到其他品种工厂的改动,例如需要扩展一个购物金检查的工厂不需要牵涉其他的改动。
PromotionCheckFactory
public interface PromotionCheckFactory {
Object getInstance(String type);
}
CouponCheckFactory
public class CouponCheckFactory implements PromotionCheckFactory {
public CouponCheck getInstance(String type) {
if ("normalCoupon".equals(type)) {
return new NormalCouponCheck();
} else if ("freightCoupon".equals(type)) {
return new FreightCouponCheck();
}
return null;
}
}
ActCheckFactory
public class ActCheckFactory implements PromotionCheckFactory {
public ActCheck getInstance(String type) {
if ("nonShoppingAct".equals(type)) {
return new NonShoppingActCheck();
} else if ("shoppingAct".equals(type)) {
return new ShoppingActCheck();
}
return null;
}
}
ActCheck
public interface ActCheck {
void checkAct();
}
CouponCheck
public interface CouponCheck {
void checkCoupon();
}
ShoppingActCheck
public class ShoppingActCheck implements ActCheck {
@Override
public void checkAct() {
System.out.println("shopping act check");
}
}
NonShoppingActCheck
public class NonShoppingActCheck implements ActCheck {
@Override
public void checkAct() {
System.out.println("check non shopping act");
}
}
NormalCouponCheck
public class NormalCouponCheck implements CouponCheck {
@Override
public void checkCoupon() {
System.out.println("check normal coupon");
}
}
FreightCouponCheck
public class FreightCouponCheck implements CouponCheck {
@Override
public void checkCoupon() {
System.out.println("check freight coupon");
}
}
Test
public class Test {
public static void main(String[] args) {
PromotionCheckFactory factory = new CouponCheckFactory();
CouponCheck normalCoupon = (CouponCheck) factory.getInstance("normalCoupon");
normalCoupon.checkCoupon();
PromotionCheckFactory factory1 = new ActCheckFactory();
ActCheck actCheck = (ActCheck) factory1.getInstance("nonShoppingAct");
actCheck.checkAct();
}
}
2.3、抽象工厂模式
抽象工厂可以生产一系列的产品,例如活动检查的工厂可以生产活动时间、活动地点、活动对象检查的对象;券检查的工厂可以生产用券时间、用券地点、用券对象检查的对象;抽象工厂可以生产一系列不同品种的(时间检查、地点检查、对象检查)对象,但是如果需要加一个品种,那么对应的所有的抽象工厂都要跟着添加这个品种创建的方法,如添加资源检查,那么活动检查的工厂和券检查的工厂都需要添加对应的创建方法。
PromotionCheckFactory
public abstract class PromotionCheckFactory {
abstract TimeCheck getTimeCheckInstance();
abstract LocationCheck getLocationCheckInstance();
}
CouponCheckFactory
public class CouponCheckFactory extends PromotionCheckFactory {
@Override
TimeCheck getTimeCheckInstance() {
return new CouponTimeCheck();
}
@Override
LocationCheck getLocationCheckInstance() {
return new CouponLocationCheck();
}
}
ActCheckFactory
public class ActCheckFactory extends PromotionCheckFactory {
@Override
TimeCheck getTimeCheckInstance() {
return new ActTimeCheck();
}
@Override
LocationCheck getLocationCheckInstance() {
return new ActLocationCheck();
}
}
TimeCheck
public interface TimeCheck {
void checkTime();
}
ActTimeCheck
public class ActTimeCheck implements TimeCheck {
@Override
public void checkTime() {
System.out.println("act time check");
}
}
CouponTimeCheck
public class CouponTimeCheck implements TimeCheck {
@Override
public void checkTime() {
System.out.println("coupon time check");
}
}
LocationCheck
public interface LocationCheck {
void checkLocation();
}
ActLocationCheck
public class ActLocationCheck implements LocationCheck {
@Override
public void checkLocation() {
System.out.println("act location check");
}
}
CouponLocationCheck
public class CouponLocationCheck implements LocationCheck {
@Override
public void checkLocation() {
System.out.println("coupon location check");
}
}
Test
public class Test {
public static void main(String[] args) {
PromotionCheckFactory checkFactory = new CouponCheckFactory();
LocationCheck checkInstance = checkFactory.getLocationCheckInstance();
checkInstance.checkLocation();
TimeCheck timeCheck = checkFactory.getTimeCheckInstance();
timeCheck.checkTime();
}
}
2.4、jdk中的工厂模式
3、建造者模式
创建者模式又叫建造者模式,是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。创建者模式隐藏了复杂对象的创建过程,它把复杂对象的创建过程加以抽象,通过子类继承或者重载的方式,动态的创建具有复合属性的对象。
ActInfoCacheDto
public class ActInfoCacheDto implements Serializable {
private static final long serialVersionUID = 9137433761199760220L;
/**
* 活动编码
*/
private String actCode;
/**
* 活动状态
*/
private Integer actStatus;
/**
* 商品范围类型
*/
private Short cmmdtyType;
public String getActCode() {
return actCode;
}
public void setActCode(String actCode) {
this.actCode = actCode;
}
public Integer getActStatus() {
return actStatus;
}
public void setActStatus(Integer actStatus) {
this.actStatus = actStatus;
}
public Short getCmmdtyType() {
return cmmdtyType;
}
public void setCmmdtyType(Short cmmdtyType) {
this.cmmdtyType = cmmdtyType;
}
@Override
public String toString() {
return "[actCode=" + actCode + ", actStatus=" + actStatus + ", cmmdtyType=" + cmmdtyType + "]";
}
}
ActInfoCacheDtoBuilder
public class ActInfoCacheDtoBuilder {
/**
* 活动编码
*/
private String actCode;
/**
* 活动状态
*/
private Integer actStatus;
/**
* 商品范围类型
*/
private Short cmmdtyType;
public static ActInfoCacheDtoBuilder create() {
return new ActInfoCacheDtoBuilder();
}
public ActInfoCacheDtoBuilder actCode(String actCode) {
this.actCode = actCode;
return this;
}
public ActInfoCacheDtoBuilder actStatus(Integer actStatus) {
this.actStatus = actStatus;
return this;
}
public ActInfoCacheDtoBuilder cmmdtyType(Short cmmdtyType) {
this.cmmdtyType = cmmdtyType;
return this;
}
public ActInfoCacheDto build() {
ActInfoCacheDto actInfoCacheDto = new ActInfoCacheDto();
actInfoCacheDto.setActCode(this.actCode);
actInfoCacheDto.setActStatus(this.actStatus);
actInfoCacheDto.setCmmdtyType(this.cmmdtyType);
return actInfoCacheDto;
}
}
Test
public class Test {
public static void main(String[] args) {
ActInfoCacheDto actInfoCacheDto = ActInfoCacheDtoBuilder.create()
.actCode("123")
.actStatus(1)
.cmmdtyType((short) 2)
.build();
System.out.println(actInfoCacheDto);
}
}
三、结构型模式
1、代理模式
1.1、静态代理
LogProxy
public class LogProxy implements IBusiness{
private IBusiness iBusiness;
public LogProxy(IBusiness iBusiness) {
this.iBusiness = iBusiness;
}
public Object doBusiness() {
System.out.println("start log ......");
Object tr = iBusiness.doBusiness();
System.out.println("end log ......");
return tr;
}
}
IBusiness
public interface IBusiness {
Object doBusiness();
}
BusinessClass
public class BusinessClass implements IBusiness {
public Object doBusiness() {
System.out.println("do business .......");
return null;
}
}
Client
public class Client {
public static void main(String args[]) {
IBusiness proxy = new LogProxy(new BusinessClass());
proxy.doBusiness();
}
}
1.2、JDK动态代理用法
Client
public class Client {
public static void main(String args[]) {
// 要代理的目标对象
ArrayList<Person> personArrayList = new ArrayList<Person>();
// 生成目标对象的代理对象,中间插入了新的执行片段
Collection o = (Collection) Proxy.newProxyInstance(ArrayList.class.getClassLoader(),
new Class[] { Collection.class }, new JdkLogInvokeHandler(personArrayList));
System.out.println(o.getClass().getName());
o.add(new Person(1, "zhang"));
System.out.println(o.size());
}
}
JdkLogInvokeHandler
public class JdkLogInvokeHandler implements InvocationHandler {
private Object target;
public JdkLogInvokeHandler(Object target) {
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("........ log start ......");
Object o = method.invoke(target, args);
System.out.println("........ log end ........");
return o;
}
}
原理
[1] 先生成被代理接口增强的代理类的字节码class文件
[2] 加载class文件
[3] 调用构造方法,把InvocationHanler对象传递进来,InvocationHanler对象中持有原来的那个被代理对象。
[4] 实际方法执行是在InvocationHandler中invoke时被代理对象执行相应的方法,同时在执行前后实现一定的功能增强
1.3、JDK动态代理模拟实现
InvocationHandler
package com.handersome.designpattern.proxy.myproxy;
public interface InvocationHandler {
Object invoke(String methodName, Class[] parmTypes);
}
Proxy
package com.handersome.designpattern.proxy.myproxy;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
public class Proxy {
public static void main(String args[]) {
generateJavaFile(Veicle.class);
}
public static Object newInstance(Class targetInterface, InvocationHandler invocationHandler) {
String filePath = generateJavaFile(targetInterface);
Object o = null;
try {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
System.out.println(compiler.getClass().getName());
StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);
Iterable<? extends JavaFileObject> units = fileMgr.getJavaFileObjects(filePath);
JavaCompiler.CompilationTask t = compiler.getTask(null, fileMgr, null, null, null, units);
t.call();
fileMgr.close();
URL[] urls = new URL[] { new URL("file:/" + "D:/test/") };
URLClassLoader ul = new URLClassLoader(urls);
Class c = ul.loadClass("myproxy." + targetInterface.getSimpleName() + "Proxy");
Constructor ctr = c.getConstructor(InvocationHandler.class);
o = ctr.newInstance(invocationHandler);
} catch (Exception e) {
e.printStackTrace();
}
return o;
}
public static String generateJavaFile(Class targetInterface) {
String str;
String interfaceName = targetInterface.getSimpleName();
Method[] declaredMethods = targetInterface.getDeclaredMethods();
String methods = "";
String returnType;
for (Method method : declaredMethods) {
returnType = method.getReturnType().getName();
Class<?>[] parameterTypes = method.getParameterTypes();
String classTypes = "";
int i = 0;
for (Class parmType : parameterTypes) {
if (i < parameterTypes.length-1) {
classTypes = classTypes + parmType.getSimpleName() + ".class,";
} else {
classTypes = classTypes + parmType.getSimpleName() + ".class";
}
}
methods = methods +
" @Override\n" +
" public long "+method.getName()+"() {\n" +
" return ("+returnType+") invocationHandler.invoke(\""+method.getName()+ "\", new Class[]{"+ classTypes+"});\n" +
" }\n" ;
}
str = "package myproxy;\n" +
"\n" +
"public class "+ interfaceName+"Proxy implements "+ interfaceName +"{\n" +
"\n" +
" private InvocationHandler invocationHandler;\n" +
"\n" +
" public "+ interfaceName+"Proxy(InvocationHandler invocationHandler) {\n" +
" this.invocationHandler = invocationHandler;\n" +
" }\n" +
"\n" +
methods
+
"}";
String filePath = null;
try {
filePath = "D:\\test\\myproxy\\" + interfaceName+"Proxy.java";
FileWriter fileWriter = new FileWriter(new File(filePath));
fileWriter.write(str);
fileWriter.flush();
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
return filePath;
}
}
1.4、问题
1、是编译时还是运行时进行代理?
运行时
2、Jdk动态代理和cglb的区别
CGLIB是一个高性能的代码生成类库,被Spring广泛应用。其底层是通过ASM字节码框架生成类的字节码,达到动态创建类的目的。
字节码创建方式:JDK动态代理通过JVM实现代理类字节码的创建,cglib通过ASM创建字节码。
JDK动态代理强制要求目标类必须实现了某一接口,否则无法进行代理。而CGLIB则要求目标类和目标方法不能是final的,因为CGLIB通过继承的方式实现代理。
CGLib不能对声明为final的方法进行代理,因为是通过继承父类的方式实现,如果父类是final的,那么无法继承父类。
对于JDK1.8及以上的版本
类的创建速度:JDK快于CGLIB。
执行速度:JDK快于CGLIB,经过努力,JDK1.8作了性能上的优化,速度明显比1.7提升了很多。1.8上JDK全面优于CGLIB,是不是说以后都不要用CGLIB,这还得看具体的类情况和场景,如果没有实现接口,就用CGLIB,使用的场景不同。
3、为什么要用代理?
在方法前或方法后灵活的添加一些逻辑,例如加一些日志打印,权限控制之类的
4、是编译时还是运行时进行代理?
运行时
5、静态代理和动态代理的区别是什么?
静态代理是通过聚合的方式实现,将被代理对象传入到代理对象中,在代理对象中调用被代理对象的方法,静态代理不方便扩张。
动态代理可以代理任何接口的任何方法,实现了灵活扩展;简单的实现方式是动态的生成代理类的类信息,然后通过编译器重新编译动态生成的类文件,然后加载类信息,生成代理类的对象,代理类就实现了对应的接口,同时会把被代理的对象传给代理的对象,代理执行执行接口方法时就会调用被代理对象执行此方法。
6、动态代理的实现过程
[1] 动态生成被代理类的类信息
代理类和被代理类java代码的异同:实现的接口相同,代理类实现方法是通过调用被代理类相应的方法完成的,代理类包含被代理类调用类InvocationHandler的成员变量,代理类通过InvocationHandler.invoke方法实现被代理类方法的调用;invoke方法中通过调用源对象的方法实现。
[2] 加载代理类
[3] 在生成代理类对象时,将被InvocationHandler传递给代理类,源对象传给InvocationHandler
[4] 通过代理类调用相关的方法,代理类里面就会调用被代理类对应的方法
对比
jdk动态代理 | cglib代理 | |
---|---|---|
实现方式 | InvocationHandler+反射 | ASM字节码编入,通过继承生成一个子类,然后修改字节码把增强的方法织入。 |
可代理的范围 | 只能代理接口 | 可以代理类 |
优点 | 需要进行反射jdk8之前执行速度没有cglib块,后面优化后速度比cglib快。 | 子类的字节码需要加载到方法区(1.6持久代,之后是元空间中),需要消耗额外的内存空间。 |
2、外观模式
门面模式将子系统中对外提供的服务封装在门面中,子系统与客户端交互通过门面实现,客户端不需要关注子系统中的实现细节
3、调停者模式
在多个类之间存在错综复杂关系的时候,为了实现解耦,创建一个调停者,类都只和调停者进行交互,由调停者实现类之间的交互。
4、适配器模式
和转接口一样,请求和服务的参数(出参、入参)不匹配,通过适配器做转化。
InputstreamReader
5、装饰器模式
允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
6、享元模式
共享元数据,从池子里获取,不再new
使用示例:String字符串常量池
7、桥接模式
多个维度排列组合时用到, 桥接模式将继承关系转换为关联关系,从而降低了类与类之间的耦合,减少了代码编写量。
礼物:维度一(温柔、狂野)、维度二(花、戒指);如果是温柔的花要用继承实现的话会有无穷无尽的组合
四、行为型模式
1、责任链模式
1.1、代码解析
Filter
public interface Filter {
void filter(Request request, Response response, FilterChain filterChain);
}
HtmlFilter
package filterchain;
public class HtmlFilter implements Filter {
@Override
public void filter(Request request, Response response, FilterChain filterChain) {
String reqStr = request.getRequestStr();
reqStr = reqStr.replaceAll("<", "[").replaceAll(">", "]") + "--HtmlFilter";
request.setRequestStr(reqStr);
filterChain.doFilter(request, response);
String resStr = response.getResponseStr();
resStr = resStr.replaceAll("<", "[").replaceAll(">", "]") + "--HtmlFilter";
response.setResponseStr(resStr);
}
}
SensitiveFilter
package filterchain;
public class SensitiveFilter implements Filter {
@Override
public void filter(Request request, Response response, FilterChain filterChain) {
String reqStr = request.getRequestStr();
reqStr = reqStr.replaceAll("敏感", "") + "--SensitiveFilter";
request.setRequestStr(reqStr);
filterChain.doFilter(request, response);
String resStr = response.getResponseStr();
resStr = resStr.replaceAll("敏感", "") + "--SensitiveFilter";
response.setResponseStr(resStr);
}
}
FilterChain
package filterchain;
import java.util.ArrayList;
import java.util.List;
public class FilterChain {
List<Filter> filterList = new ArrayList<>();
int index = 0;
public FilterChain addFilter(Filter filter) {
filterList.add(filter);
return this;
}
public void doFilter(Request request, Response response) {
if (index > filterList.size() - 1) {
return;
}
Filter filter = filterList.get(index);
index++;
filter.filter(request, response, this);
}
}
Request
package filterchain;
public class Request {
private String requestStr;
public String getRequestStr() {
return requestStr;
}
public void setRequestStr(String requestStr) {
this.requestStr = requestStr;
}
@Override
public String toString() {
return "[" +
"requestStr=" + requestStr +
"]";
}
}
Response
package filterchain;
public class Response {
private String responseStr;
public String getResponseStr() {
return responseStr;
}
public void setResponseStr(String responseStr) {
this.responseStr = responseStr;
}
@Override
public String toString() {
return "[" +
"responseStr=" + responseStr +
"]";
}
}
Main
package filterchain;
public class Main {
public static void main(String args[]) {
String reqStr = "<scgg>, 这是敏感词汇";
Request request = new Request();
request.setRequestStr(reqStr);
String resStr = "<scgg1>, 这是敏感词汇1";
Response response = new Response();
response.setResponseStr(resStr);
FilterChain filterChain = new FilterChain()
.addFilter(new HtmlFilter())
.addFilter(new SensitiveFilter());
filterChain.doFilter(request, response);
System.out.println(request);
System.out.println(response);
}
}
输出结果
[requestStr=[scgg], 这是词汇--HtmlFilter--SensitiveFilter]
[responseStr=[scgg1], 这是词汇1--SensitiveFilter--HtmlFilter]
1.2、结构图
1.3、源码中的使用示例
tomcat中的过滤器
zookeeper中的请求处理器
requestProcessor
2、迭代器模式
迭代模式主要在容器设计时使用
Collection
/**
* 集合接口
* @author : 18073771
* @see [相关类/方法](可选)
* @since [产品/模块版本] (可选)
*/
public interface Collection<E> {
void add(E object);
int size();
}
Iterable
/**
* @author : 18073771
* @see [相关类/方法](可选)
* @since [产品/模块版本] (可选)
*/
public interface Iterable<E> {
Iterator<E> iterator();
}
Iterator
/**
* 迭代器
* @author : 18073771
* @see [相关类/方法](可选)
* @since [产品/模块版本] (可选)
*/
public interface Iterator<E> {
boolean hasNext();
E next();
}
ArrayList
/**
* arraylist实现
* @author : 18073771
* @see [相关类/方法](可选)
* @since [产品/模块版本] (可选)
*/
public class ArrayList<E> implements Collection<E>, Iterable<E> {
// 设置一个容器存数据
private E[] array = (E[]) new Object[10];
// 容器的下标
private int index = 0;
/**
* 添加元素的方法
*
* @param object
*/
public void add(E object) {
if (index >= array.length) {
E[] newArray = (E[]) new Object[index * 2];
System.arraycopy(array, 0, newArray, 0, array.length);
array = newArray;
}
array[index] = object;
index++;
}
/**
* 容器的大小
*
* @return
*/
public int size() {
return index;
}
/**
* 容器迭代器
*
* @return
*/
public Iterator<E> iterator() {
return new ArrayListItr();
}
/**
* 迭代器内部实现
*/
private class ArrayListItr implements Iterator {
int flag = 0;
public boolean hasNext() {
if (flag < array.length - 1 && array[flag] != null) {
return true;
}
return false;
}
public E next() {
E obj = array[flag];
flag++;
return obj;
}
}
}
Main
public class Main {
public static void main(String args[]) {
ArrayList<Person> personList = new ArrayList<Person>();
for (int i=0;i<15;i++) {
personList.add(new Person(i+1, "name" + i));
}
System.out.println(personList.size());
Iterator<Person> iterator = personList.iterator();
Person person;
while (iterator.hasNext()) {
person = iterator.next();
System.out.println(person);
}
}
}
Person
public class Person {
private int id;
private String name;
public Person(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "[id=" + id + ", name=" + name + "]";
}
}
测试结果
15
[id=1, name=name0]
[id=2, name=name1]
[id=3, name=name2]
[id=4, name=name3]
[id=5, name=name4]
[id=6, name=name5]
[id=7, name=name6]
[id=8, name=name7]
[id=9, name=name8]
[id=10, name=name9]
[id=11, name=name10]
[id=12, name=name11]
[id=13, name=name12]
[id=14, name=name13]
[id=15, name=name14]
3、策略模式
3.1 、思想
【1】什么是策略?
策略是达成目的的一种具体实现,例如,要到一个地方去,可以做飞机、火车等每种方式就是一种策略;同样促销打折,满元减元、满件减件、每元减元、每件减件、满元打折这些都是实现活动促销的策略。策略与策略之间是可以切换的,可以不断扩展的。
【2】什么是策略模式?
策略模式就是将各个不同的策略封装起来,更具具体场景的不同实现不同策略之间的切换。
3.2、代码
java中的比较器就是采用的策略模式
XXComparator
实现身高比较的比较器
package strategy1;
import java.util.Comparator;
public class HeightComparator implements Comparator<Person> {
@Override
public int compare(Person o1, Person o2) {
if (o1.getHeight() > o2.getHeight()) {
return 1;
} else {
return -1;
}
}
}
实现重量比较的比较器
package strategy1;
import java.util.Comparator;
public class WeightComparator implements Comparator<Person> {
@Override
public int compare(Person o1, Person o2) {
if (o1.getWeight() > o2.getWeight()) {
return 1;
} else {
return -1;
}
}
}
Person
package strategy1;
public class Person {
private int height;
private int weight;
private String name;
public Person(String name, int height, int weight) {
this.name = name;
this.height = height;
this.weight = weight;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "[height=" + height + ", weight=" + weight + ", name=" + name + "]";
}
}
排序的Main
package strategy1;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Main {
public static void main(String args[]) {
List<Person> personList = new ArrayList<>();
Person person1 = new Person("张三", 163, 120);
personList.add(person1);
Person person2 = new Person("李四", 180, 150);
personList.add(person2);
Person person3 = new Person("王五", 175, 190);
personList.add(person3);
// 比较策略1
Collections.sort(personList, new HeightComparator());
System.out.println("按身高排序:" + personList);
// 比较策略2
Collections.sort(personList, new WeightComparator());
System.out.println("按重量排序:" + personList);
}
}
结果
按身高排序:[[height=163, weight=120, name=张三], [height=175, weight=190, name=王五], [height=180, weight=150, name=李四]]
按重量排序:[[height=163, weight=120, name=张三], [height=180, weight=150, name=李四], [height=175, weight=190, name=王五]]
3.3 促销中的策略模式思考
4、观察者模式
事件的处理通常是观察者+责任链
给事件注册观察者,事件发生时通知观察者执行
Subject
public interface Subject {
void add(Observer o);
void del(Observer o);
void notifyObserver();
void operation();
}
AbstractSubject
public abstract class AbstractSubject implements Subject {
private List<Observer> list=new ArrayList<Observer>();
@Override
public void add(Observer o) {
list.add(o);
}
@Override
public void del(Observer o) {
list.remove(o);
}
@Override
public void notifyObserver() {
for(int i=0;i<list.size();i++){
Observer o=list.get(i);
o.update();
}
}
}
MySubject
public class MySubject extends AbstractSubject{
public void operation(){
System.out.println("itself update");
this.notifyObserver();
}
}
Observer
public interface Observer {
void update();
}
Observer1
public class Observer1 implements Observer {
@Override
public void update() {
System.out.println("observer 1 received!");
}
}
5、命令模式
将请求封装到对象中,支持撤销操作;主要体现在请求和撤销对应的这个语义关系上。
五、设计模式总结
1、指导思想
可维护性
可扩展性
可复用性
灵活性
2、原则
单一职责:高内聚低耦合
开闭原则:多扩展开放,对修改关闭
李氏替换原则:使用父类的地方能使用子类替换
依赖倒置:面向接口编程
接口隔离原则:高内聚低耦合
迪米特法则:不用和非本类无关的类