单例模式 Singleton
懒汉模式 lazy loading
有多种,用的不多,不推荐使用
饿汉模式
推荐使用,简单粗暴,没那么复杂,项目中用到最多的模式也是这个
public static T INSTANCE = new T();
private T (){};
最完美的模式 enum模式
effective java 作者推荐的模式,保证单例,且不会被反序列化实例出来(即不会被反射创建出来)
public enum T{
INSTANCE;
}
策略模式 Strategy
最典型的例子是jdk的Comparator比较器。本质就是传个function进去。
public BiFunction<Integer,Integer,Integer> calculator;
public BiFunction<Integer,Integer,Integer> addiotnCalculator = (p0,p1)->p0+p1;
public BiFunction<Integer, Integer, Integer> multiplicationCalculator = (p0, p1) -> p0 * p1;
public int calculator (int param0,int param1){
calculator = addiotnCalculator;
//calculator = multiplicationCalculator;
return calculator.apply(param0,param1);
}
工厂模式 Factory 以及 抽象工厂模式 AbstractFactory
工厂:实例不由自己去创建,而交给工厂创建,项目代码
抽象工厂:## 标题创建工厂的工厂
public class AbstractFactoryPattern {
private static final Data DB_DMG = DataFactory.newFactory("Db").newDataInstance(new Object());
private static final Data MC_DMG = DataFactory.newFactory("Redis").newDataInstance(new Object());
}
abstract class DataFactory{
abstract Data newDataInstance(Object param);
static DataFactory newFactory(String factoryName){
if(Objects.equals(factoryName,"Db")){
return new DbDataFactory();
}
if(Objects.equals(factoryName,"Redis")){
return new RedisDataFactory();
}
DataFactory defaultFactory = null;
return defaultFactory;
}
}
class DbDataFactory extends DataFactory{
Data newDataInstance(Object param){
int tableId = 0;
int dataId = 1;
return new DbData(tableId,dataId);
}
}
class RedisDataFactory extends DataFactory{
Data newDataInstance(Object param){
String reidsKey = "";
return new RedisData(reidsKey);
}
}
abstract class Data{
abstract int get(int userId);
abstract void set(int userId);
}
class DbData extends Data{
int tableId;
int dataId;
public DbData(int tableId, int dataId) {
this.tableId = tableId;
this.dataId = dataId;
}
@Override
int get(int userId) {
/*mysql操作*/
return 0;
}
@Override
void set(int userId) {
/*mysql操作*/
}
}
class RedisData extends Data{
String reidsKey;
public RedisData(String reidsKey) {
this.reidsKey = reidsKey;
}
@Override
int get(int userId) {
/*redis操作*/
return 0;
}
@Override
void set(int userId) {
/*redis操作*/
}
}
门面模式 Facade和Meidator
简单的说就是把所有的相关的操作全部聚合到一个类中
class Person(){
int id;
Clothes clothes;
Pet pet;
...
}
class PersonUtil{
ClothesManager clothesManager;
PetManager petManager;
...
/*通过id拿到clothes*/
Clothes getClothes(int id){
/*clothesManager里面有自己的业务逻辑*/
clothesManager.get(id);
}
/*通过id拿到pet*/
Pet getPet(int id){
/*petManager里面有自己的业务逻辑*/
petManager.get(id);
}
...
}
装饰器模式 Decorator
这个平时没怎么用到,理解的还不是很深,简单的用代码实现一下,方便后面自己理解
interface Decorator{
void decorate();
}
class ADecorator implements Decorator{
void decorate(){
}
}
class BDecorator implements Decorator{
Decorator decorator;
public BDecorator(Decorator decorator){
this.decorator = decorator;
}
void decorate(){
/*自己需要的业务逻辑*/
decorator.decorate();
}
}
责任链 Chain Of Responsibility
非常重要,也非常实用。简单的来说就是用一个for循环
最典型的例子,filter的实现。
项目中的代码,判断技能是否命中:
private void executeSingle() {
beforeCast(param);
// 计算命中伤害前如果死亡则技能无效
if (hasEffect(param)) {
//技能命中业务代码
} else {
//技能没命中业务代码
}
endCast(param);
}
boolean hasEffect(Param param){
/*这里采用的就是责任链模式,若有个buff是必定闪避,则只要在改buff生成的
status里面将hasEffect重新为return false,就可以实现该逻辑*/
List<Status> statusList = param.getAllStatus();
for(Status s:statusList){
if(!s.hasEffect()){
return false;
}
}
//其他的判断
return true;
}
观察者模式 Observer
同样非常重要,也非常实用。简单的来说就是将function存在一个list里面,然后触发某个时间可以依次执行list里面的函数。
resoucre,信息源,抛出event的地方,就是在哪里触发的
event,事件本身,可以理解为function的参数
listener,监听者,事件触发后的执行,可以理解为function本身
典型例子为键盘和鼠标的响应事件
在项目之中的应用
class EventDispatcher{
private static HashMap<Class, List<ListenerWrap>> map;
static{
//这里将监听者注册到map里面,这里只是方便演示,项目中用的是反射将所有监听事件注册进来
AListen aListen = new AListen();
Method[] methods = aListen.getClass().getMethods();
for (Method method:methods){
EventInject ei = m.getAnnotation(EventInject.class);
if(ei != null){
map.get(ei.value).add(new ListenerWrap(method,aListen));
}
}
}
public static boolean dispatch(Event event) {
List<ListenerWrap> listenerList = map.get(event.class);
for(ListenerWrap l:listenerList){
l.invoke(event);
}
}
}
class ListenerWrap(){
public Method method;
public Object inv;
public ListenerWrap(Method method,Object inv){
this.method = method;
this.inv = inv;
}
invoke(Event event){
method.invoke(inv,event);
};
}
class Resoucre{
void A(){
//其他代码
EventDispatcher.dispatch(new XEvent(Object param))
}
}
class Event{}
class XEvent extends Event{
Object param;
public XEvent(Object param){
this.param = param;
}
}
class AListen{
@EventInject(XEvent.class)
public void listen(XEvent event){
//业务逻辑
}
}
组合模式 Composite
一个树状结构,分为叶子节点和非叶子节点
典型例子为文件系统
public class Composite {
public static void main(String[] args) {
Directory root = new Directory("root");
File f1 = new File("file1");
File f2 = new File("file1");
Directory d1 = new Directory("directory1");
Directory d2 = new Directory("directory2");
root.addNode(f1);
root.addNode(f2);
root.addNode(d1);
root.addNode(d2);
File f11 = new File("file11");
File f12 = new File("file12");
d1.addNode(f11);
d1.addNode(f12);
File f21 = new File("file21");
File f22 = new File("file22");
d2.addNode(f21);
d2.addNode(f22);
print(root, 0);
}
private static void print(Node root, int depth) {
for (int i = 0; i < depth; i++) {
System.out.print("--");
}
System.out.println(root.name);
if (root instanceof Directory) {
Directory d = (Directory) root;
for (Node n : d.nodes) {
print(n, depth + 1);
}
}
}
}
abstract class Node {
String name;
public Node(String name) {
this.name = name;
}
}
class File extends Node {
public File(String name) {
super(name);
}
}
class Directory extends Node {
List<Node> nodes = new ArrayList<>();
public Directory(String name) {
super(name);
}
void addNode(Node node) {
nodes.add(node);
}
}
享元模式 flyweight
池化技术,创建一个池回收对象,减少对象的创建和销毁
String,Integer,线程池,连接池都属于该模式
备忘录模式 Memento
数据持久化
java中采用serializable将对象序列化储存,利用transient关键字可以将字段不序列化
public class Memento {
MementoSerializable m = new MementoSerializable();
public static void main(String[] args) throws Exception{
Memento memento = new Memento();
memento.save();
MementoSerializable nm = memento.load();
/*MementoSerializable{id=0, name='dream', age=0}*/
System.out.println(nm.toString());
}
private void save() throws Exception {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\MementoSerializable.data"));
oos.writeObject(m);
oos.flush();
oos.close();
}
private MementoSerializable load() throws Exception{
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\MementoSerializable.data"));
MementoSerializable nm = (MementoSerializable)ois.readObject();
ois.close();
return nm;
}
}
class MementoSerializable implements Serializable {
int id = 0;
String name = "dream";
transient int age = 22;
@Override
public String toString() {
return "MementoSerializable{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
原型模式 Prototype
对象的拷贝
java中实现Cloneable将对象浅拷贝,深拷贝则需要将对象的属性也加上Cloneable。另外String类型是属于深拷贝的,具体实现是String的池化技术和final关键字。
模板模式 Template
项目常用,比如说一个命令的接收,我们只需要关注doSome的具体业务实现,而不用关注全部的流程实现
public abstract class Father{
public void receive(User u,Param param){
Response re = new Response();
doSome(u,param,re);
sendResponse(u,re);
}
protected abstract void doSome(User u,Param param,Response re);
}
public class Child{
@Override
protected void doSome(User u,Param param,Response re){
//dosomething
}
}
代理模式 proxy
静态代理
与 decorate几乎一样
动态代理
使用Proxy.Proxy.newProxyInstance()方法
public class Main3 {
public static void main(String[] args) {
Movable c = (Movable)Proxy.newProxyInstance(Car.class.getClassLoader(), new Class[]{Movable.class},new CarInvocationHandler(new Car()));
c.move();
}
}
class CarInvocationHandler implements InvocationHandler{
Movable m;
public CarInvocationHandler(Movable m) {
this.m = m;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before");
Object result = method.invoke(m,args);
System.out.println("end");
return result;
}
}
class Car implements Movable{
@Override
public void move() {
System.out.println("car move");
}
}
interface Movable{
void move();
}
迭代器模式 Iterator
典型例子:List 的next()和hasNext()方法
访问者模式 visitor
适合结构固定的
建造者模式 Builder
实例时可以选择需要的参数进行实例,且不用写过多的构造方法
public class Main4 {
int a;
int b;
int c;
int d;
int g;
public static void main(String[] args) {
Main4 m = new Buider().
setA(1).
// setB(2).
setC(3).
// setD(4).
build();
}
}
class Buider{
Main4 m;
Buider(){
m = new Main4();
}
public Buider setA(int a){
m.a = a;
return this;
}
public Buider setB(int b){
m.b = b;
return this;
}
public Buider setC(int c){
m.c = c;
return this;
}
public Buider setD(int d){
m.d = d;
return this;
}
public Main4 build() {
return m;
}
}
适配器模式 Adapter
将接口类型不一致的两个类通过第三个类关联起来
典型例子 callable和Thread
public static void main(String[] args) throws Exception{
Callable<Integer> c = ()->1;
/*FutureTask充当适配器角色*/
FutureTask<Integer> f = new FutureTask(c);
Thread t = new Thread(f);
t.start();
System.out.println(f.get());
}
命令行模式 Command
撤销(undo),回滚(rollback)等操作
总结
设计模式的本质就是多态,所以不用太过于纠结。做好四大性能和遵循六大原则就行
四大性能
- 可维护性 maintainability
- 可复用性 reusability
- 可扩展性 scalability/extensibility
- 灵活性 flexibility/mobility/adaptability
六大原则
- 单一职责原则 single responsibility principle
- 开闭原则 open-closed principle
- 依赖倒置原则 dependency inversion principle
- 接口隔离原则 interface segregation principle
- 里氏替换原则 Liskov Substitution principle
- 高内聚 低耦合原则 minimize coupling