设计模式
最近在看设计模式之禅,总结一下23种模式
单例模式
案例引入
我是皇帝,天底下只能由我一个,唯我独尊
具体代码
懒汉式
public class Single {
private Single() {
}
private static Single single = null;
public static Single getInstance() {
if (single == null) {
single = new Single();
}
return single;
}
}
饿汉式
public class Single {
private Single() {
}
private static final Single single = new Single();
public static Single getInstance() {
return single;
}
}
优点
- 内存中只有一个实例,减少了内存开销
- 避免了对资源的多重占用
- 设置全局的访问点
缺点
- 一般没有接口,难以扩展
- 对于测试不利
- 与单一职责原则有冲突
使用场景
- 生成唯一序列号的环境
- 整个项目需要一个共享访问点或共享数据
- 创建一个对象需要消耗的资源过多
- 需要定义大量的静态常量和静态方法
注意事项
- 高并发情况注意线程同步问题
工厂模式
案例引入
女娲用八卦炉造人
具体代码
public class personFactory {
public <T extends Person> T createPerson(Class<T> c) {
Person person=null;
try {
person=(Person)Class.forName(c.getName()).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return (T)person;
}
}
public interface Person {
void complexion();
void talk();
}
public class black implements Person {
@Override
public void complexion() {
System.out.println("黑种人");
}
@Override
public void talk() {
System.out.println("我是黑人");
}
}
public class white implements Person {
@Override
public void complexion() {
System.out.println("白种人");
}
@Override
public void talk() {
System.out.println("我是外国人");
}
}
public class yellow implements Person {
@Override
public void complexion() {
System.out.println("黄种人");
}
@Override
public void talk() {
System.out.println("我是黄种人");
}
}
personFactory personFactory = new personFactory();
Person person1 = personFactory.createPerson(yellow.class);
person1.complexion();
person1.talk();
Person person2 = personFactory.createPerson(white.class);
person2.complexion();
person2.talk();
Person person3 = personFactory.createPerson(black.class);
person3.complexion();
person3.talk();
优点
- 降低模块之间的耦合
使用场景
- 是new的一个代替品
- 需要灵活的,可扩展的框架
抽象工厂模式
案例引入
女娲造人不能只分为黄,黑,白吧,还得是男女对不对?
具体代码
public interface Person {
void complexion();
void talk();
void sex();
}
public abstract class black implements Person {
@Override
public void complexion() {
System.out.println("黑种人");
}
@Override
public void talk() {
System.out.println("我是黑人");
}
}
public class FemaleBlack extends black {
public void sex() {
System.out.println("黑人女性");
}
}
public interface personFactory {
public Person createYellow();
public Person createWhile();
public Person createBlack();
}
public class MaleFactory implements personFactory {
@Override
public Person createYellow() {
return null;
}
@Override
public Person createWhile() {
return null;
}
@Override
public Person createBlack() {
return new FemaleBlack();
}
}
MaleFactory maleFactory=new MaleFactory();
Person black=maleFactory.createBlack();
black.sex();
优点
- 封装性
- 约束变为非公开状态
缺点
- 扩展困难
使用场景
一组对象都有相同的约束,则可以使用抽象工厂模式
模板方法模式
案例引入
制造车子,客户检验车的质量
具体代码
public abstract class Car {
public abstract void start();
public abstract void alarm();
public abstract void stop();
public void run() {
this.start();
this.alarm();
this.stop();
}
}
public class CarModel extends Car {
@Override
public void start() {
System.out.println("启动");
}
@Override
public void alarm() {
System.out.println("鸣喇叭");
}
@Override
public void stop() {
System.out.println("停车");
}
}
Car car=new CarModel();
car.run();
优点
- 封装不变部分,扩展可变部分
- 提取公共部分代码,便于维护
- 行为又父类控制,子类实现
使用场景
-
多个子类有共有的方法,基本逻辑相同
-
重要的算法设计为模板方法,细节功能又子类实现
-
相同的代码抽取到父类,通过钩子函数约束行为(如下)
扩展
public abstract class Car {
public abstract boolean isAlarm();
public abstract void start();
public abstract void alarm();
public abstract void stop();
public void run() {
this.start();
if (this.isAlarm()) {
this.alarm();
}
this.stop();
}
}
public class CarModel extends Car {
public boolean alarmFlag=true;
@Override
public void start() {
System.out.println("启动");
}
@Override
public void alarm() {
System.out.println("鸣喇叭");
}
@Override
public void stop() {
System.out.println("停车");
}
public boolean isAlarm() {
return alarmFlag;
}
public void setAlarmFlag(boolean alarmFlag) {
this.alarmFlag = alarmFlag;
}
}
建造者模式
案例引入
造了车之后,测试的顺序可能不同,不一定是启动,鸣喇叭,停车,也可以是鸣喇叭,启动,停车等等,如果需求多了,我们可以定义一个建造者,你要啥循序都告诉建造者
具体代码
public abstract class Car {
public ArrayList<String> sequence = new ArrayList<>();
public abstract boolean isAlarm();
public abstract void start();
public abstract void alarm();
public abstract void stop();
public void run() {
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("alarm")) {
this.alarm();
} else if (actionName.equalsIgnoreCase("stop")) {
this.stop();
}
}
}
public void setSequence(ArrayList<String> sequence) {
this.sequence = sequence;
}
}
public class CarModel extends Car {
@Override
public void start() {
System.out.println("启动");
}
@Override
public void alarm() {
System.out.println("鸣喇叭");
}
@Override
public void stop() {
System.out.println("停车");
}
}
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("alarm");
arrayList.add("start");
arrayList.add("stop");
car.setSequence(arrayList);
car.run();
优点
- 建造者独立
- 便于控制细节
- 封装线
使用场景
- 相同的方法,不同的执行顺序
- 多个部件,可以装配到一个对象中,但是产生的运行结果不相同
- 产品类非常复杂
代理模式
案例引入
游戏代练(不提倡这种行为哟),明星和经纪人
具体代码
- 动态代理
public interface Player {
void login();
void boss();
void stop();
}
public class sPlayer implements Player {
@Override
public void login() {
System.out.println("登陆账号");
}
@Override
public void boss() {
System.out.println("打boss");
}
@Override
public void stop() {
System.out.println("退出游戏");
}
}
Player sPlayer=new sPlayer();
Player proxyPlayer = (Player) Proxy.newProxyInstance(test.class.getClassLoader(),
sPlayer.class.getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("-");
Object object=method.invoke(sPlayer, args);
System.out.println("=");
return object;
}
});
proxyPlayer.login();
proxyPlayer.boss();
proxyPlayer.stop();
优点
- 职责清晰:真实的角色就是实现实际的业务逻辑,不用关心其他飞奔职责的事务
- 高扩展性
- 智能化
使用场景
- Spring的AOP