一、理论部分
1.单一职责原则
2.开放-封闭原则
对扩展开放,对更改封闭
3.依赖倒转原则
抽象不应该依赖细节,细节应该依赖抽象
4.里氏代换原则
子类型必须能够替换掉父类型
5.迪米特法则
如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者妆发这个调用。
二、创建型模式
1.工厂方法模式
定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法是一个类的实例化延迟到其子类
以雷锋为例>
雷锋工厂
public interface LeiFenFactory {
LeiFen createLeiFen();
}
雷锋抽象类(规定了雷锋的方法)
public abstract class LeiFen {
abstract void sweep();
abstract void buyVegetables();
abstract void mop();
}
学生类继承雷锋父类实现雷锋接口
public class StudentLF extends LeiFen implements LeiFenFactory{
private String beneficiaries ;
public String getBeneficiaries() {
return beneficiaries;
}
public void setBeneficiaries(String beneficiaries) {
this.beneficiaries = beneficiaries;
}
public StudentLF() {
}
public StudentLF(String beneficiaries) {
this.beneficiaries = beneficiaries;
}
@Override
void sweep() {
System.out.println("学生学习雷锋帮助"+beneficiaries+"扫地");
}
@Override
void buyVegetables() {
System.out.println("学生学习雷锋帮助"+beneficiaries+"买菜");
}
@Override
void mop() {
System.out.println("学生学习雷锋帮助"+beneficiaries+"刷碗");
}
@Override
public LeiFen createLeiFen() {
return new StudentLF(beneficiaries);
}
}
社会工作者类继承雷锋父类继承雷锋接口
public class socialWorkerLF extends LeiFen implements LeiFenFactory{
private String beneficiaries ;
public String getBeneficiaries() {
return beneficiaries;
}
public void setBeneficiaries(String beneficiaries) {
this.beneficiaries = beneficiaries;
}
public socialWorkerLF() {
}
public socialWorkerLF(String beneficiaries) {
this.beneficiaries = beneficiaries;
}
@Override
void sweep() {
System.out.println("社会工作者学习雷锋帮助"+beneficiaries+"打扫");
}
@Override
void buyVegetables() {
System.out.println("社会工作者学习雷锋帮助"+beneficiaries+"买菜");
}
@Override
void mop() {
System.out.println("社会工作者学习雷锋帮助"+beneficiaries+"刷碗");
}
@Override
public LeiFen createLeiFen() {
return new socialWorkerLF(beneficiaries);
}
}
具体调用
public class Main {
public static void main(String[] args) {
LeiFenFactory leiFenFactory = new StudentLF("李老汉");
LeiFen student1 = leiFenFactory.createLeiFen();
student1.sweep();
student1.buyVegetables();
student1.mop();
}
}
2.抽象工厂模式
提供一个创建一系列相关或者相互依赖对象的接口,而无需指定他们具体的类。
角色
- 抽象工厂(Abstract Factory)。 提供了创建产品的接口,它包含多个创建产品的方法newProduct(),可以创建多个不同等级的产品
- 【手机工厂】
- 具体工厂(Concrete Factory)。实现抽象工厂中的多个抽象方法,完成具体产品的创建
- 【OPPO工厂、VIVO工厂、华为工厂】
- 抽象产品(Product)定了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品.
- 【CPU、内存、麦克风】【这里加产品抽象工厂需同步新增对应方法】
- 具体产品(Concrete Product)实现了抽象产品角色多定义的接口,由具体工厂来创建,它同具体工厂之间是多对一的关系
- 【OPPO手机、VIVO手机】
3.单例模式
保证一个类只有一个实例,并提供一个能够访问他的全局访问点。
实现方式一 饿汉式
public class HungryStyle {
//在类加载阶段就初始化对象为一个对象实例,并对此对象实例进行私有化封装
private final static HungryStyle HUNGRY_STYLE = new HungryStyle();
//用private修饰该类的无参构造器,使该类不能通过new对象的方式进行初始化
private HungryStyle(){
}
//提供一个公共的静态方法,使外界调用此方法来实现对对象的初始化
public static HungryStyle getObject(){
return HUNGRY_STYLE;
}
}
实现方式二 懒汉式
需要注意的是此种实现方式可能会在多线程环境下造成线程不安全的情况,因此要进行双重判空和加锁来保证线程的安全,相较于饿汉式,懒汉式通过懒加载的方式避免了在类加载阶段就初始化对象为实例对于堆内存的浪费。
public class LazyStyle {
private static LazyStyle lazyStyle;
//私有化封装,禁止new对象的方式创建实例
private LazyStyle(){
}
public static LazyStyle getLazyStyle(){
//第一次判断是否为空,null则放行,非空则直接返回现有的lazyStyle实例
if(lazyStyle == null){
//对lazyStyle加锁
synchronized (lazyStyle){
//判断当前lazyStyle是否为空防止第一个判断漏过来的线程在等待时间lazyStyle已经被初始化
if(lazyStyle == null){
lazyStyle = new LazyStyle();
}
}
}
return lazyStyle;
}
}
实现方式三 静态内部类
通过静态内部类实现懒加载
public class StaticStyle {
//利用静态内部类的特性,只有在StaticHolder第一次被调用时才会初始化对象
private static class StaticHolder{
private final static StaticStyle STATIC_STYLE = new StaticStyle();
}
//私有化封装,阻止外部通过new对象的方式初始化对象
private StaticStyle(){
}
//当执行getStaticStyle时才会第一次调用StaticHolder,此时初始化对象并返回
//同样实现了线程安全和懒加载
public static StaticStyle getStaticStyle(){
return StaticHolder.STATIC_STYLE;
}
}
实现方式四 枚举
public enum EnumStyle {
INSTANCE;
}
4.建造者模式
建造者模式使建造代码于表示代码分离,使得相同的构建过程可以构建不同的表示。由于建造者隐藏了该产品是如何组装的,所以需要改变一个产品的内部表示再定义一个具体的建造者就可以了。
建造模式是在当创建复杂对象的算法,应该独立于该对象的组成部分以及它们的装配方式时适用的模式。
以做菜为例表示建造者模式>
建造者接口
public interface Builder {
void seasoning(); //调料
void edibleOil(); //油
void cooking(); //烹饪方式
void potType(); //锅类型
void entree(); //主菜
Product gteResult();
}
汉堡类实现建造者接口
public class BuilderHamburg implements Builder{
Product product = new Product();
@Override
public void seasoning() {
product.addPart("盐,番茄酱,沙拉酱,芝士");
}
@Override
public void edibleOil() {
product.addPart("油炸肉饼");
}
@Override
public void cooking() {
product.addPart("煎炸");
}
@Override
public void potType() {
product.addPart("方形油炸锅");
}
@Override
public void entree() {
product.addPart("面包片,生菜片,肉饼,西红柿片");
}
@Override
public Product gteResult() {
return product;
}
}
面条类同样实现建造者接口
public class BuilderNoodles implements Builder{
Product product = new Product();
@Override
public void seasoning() {
product.addPart("盐,酱油,胡椒粉");
}
@Override
public void edibleOil() {
product.addPart("加少量油");
}
@Override
public void cooking() {
product.addPart("煮");
}
@Override
public void potType() {
product.addPart("铁锅");
}
@Override
public void entree() {
product.addPart("面条,油麦菜");
}
@Override
public Product gteResult() {
return product;
}
}
指挥者——构建一个使用Builder接口的对象
public class Director {
Builder builder ;
public Director(Builder builder) {
this.builder = builder;
}
public void DirectorBuild(){
builder.potType();
builder.entree();
builder.seasoning();
builder.edibleOil();
builder.cooking();
}
}
产品类
import java.util.LinkedList;
public class Product {
LinkedList<String> parts = new LinkedList<String>();
public void addPart(String part){
parts.add(part);
}
public void show(){
System.out.println("产品创建:");
for (String part : parts) {
System.out.println(part);
}
}
}
具体调用
public class Main {
public static void main(String[] args) {
Builder builder = new BuilderHamburg();
Director director = new Director(builder);
director.DirectorBuild();
Product product = builder.gteResult();
product.show();
}
}
5.原型模式
用原型实例制定创建对象的种类,并且通过拷贝这些圆形创建新的对象。
在java中可以通过实现Cloneable接口来实现拷贝
以简历为例>
public class Biographical implements Cloneable{
private String name ;
private int age;
private String sex;
private Experience experience;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Experience getExperience() {
return experience;
}
public void setExperience(Experience experience) {
this.experience = experience;
}
public Biographical() {
}
public Biographical(String name, int age, String sex, Experience experience) {
this.name = name;
this.age = age;
this.sex = sex;
this.experience = experience;
}
@Override
public String toString() {
return "Biographical{" +
"name='" + name + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
", experience=" + experience.toString() +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
Biographical copy = (Biographical) super.clone();
copy.experience = (Experience) this.experience.clone();
return copy;
}
}
拷贝过程分为浅拷贝和深拷贝,浅拷贝在涉及到引用数据类型对象的复制时会复制引用数据类型对象的地址,而深拷贝在复制引用数据类型时则会创建新的对象并进行拷贝。
以自行定义的Experience类型为例,在Java语言中可以通过使拷贝的对象实现Cloneable接口实现深拷贝。
import java.util.Date;
public class Experience implements Cloneable{
private String companyName;//公司名
private Date startDate;//开始时间
private Date endDate; //结束时间
private String undergo;//经历
public Experience() {
}
public Experience(String companyName, Date startDate, Date endDate, String undergo) {
this.companyName = companyName;
this.startDate = startDate;
this.endDate = endDate;
this.undergo = undergo;
}
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
public Date getStartDate() {
return startDate;
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
public Date getEndDate() {
return endDate;
}
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
public String getUndergo() {
return undergo;
}
public void setUndergo(String undergo) {
this.undergo = undergo;
}
@Override
public String toString() {
return "Experience{" +
"companyName='" + companyName + '\'' +
", startDate=" + startDate +
", endDate=" + endDate +
", undergo='" + undergo + '\'' +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
具体调用
import java.util.Date;
public class Main {
public static void main(String[] args) throws CloneNotSupportedException {
Biographical biographical = new Biographical();
Experience experience = new Experience("NEUSoft",new Date(2024,7,2),new Date(2024,8,1),"从事java开发工作");
biographical.setName("张三");
biographical.setAge(22);
biographical.setSex("女");
biographical.setExperience(experience);
Biographical lisi = (Biographical) biographical.clone();
lisi.getExperience().setStartDate(new Date(2024,7,1));
System.out.println(biographical);
System.out.println(lisi);
}
}
三、结构型模式
1.适配器模式
适配器模式,将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
实例》
创建Target接口规范
public interface Target {
void general() throws ClassNotFoundException;
}
创建Target实现类
public class TargetA implements Target{
@Override
public void general() throws ClassNotFoundException {
System.out.println(Class.forName("designMode.AdapterPattern.TargetA"));
}
}
来自另一套规范的类Adaptee
public class Adaptee {
public void Special() throws ClassNotFoundException {
System.out.println(Class.forName("designMode.AdapterPattern.Adaptee"));
}
}
创建适配器使两者在调用层面一致
public class Adapter implements Target{
Adaptee adaptee ;
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void general() throws ClassNotFoundException {
adaptee.Special();
}
}
适配器模式一般适用于代码维护中出现,在想使用一个已经存在的类,但是如果他的接口,也就是他的方法和你的要求不相同时,就应该考虑使用适配器模式。也就是两个类所做的事情相同或类似,但是具有有不同的接口时可以考虑使用它。
2.装饰器模式
装饰模式,动态的给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更加灵活。
实例——以衣服为例》
创建一个穿着的抽象父类
public abstract class ClothingDecorator implements Person{
protected Person person;
public void Decorator(Person person) {
this.person = person;
}
@Override
public void showDress() {
if(person!=null){
person.showDress();
}
}
}
创建一个人类的抽象父类
public abstract class Human{
private String name ;
private String age;
public Human() {
}
public Human(String name, String age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
}
构建一个人类的接口
public interface Person {
public void showDress();
}
构建一个衬衫类继承自穿着父类
public class ShirtDecorator extends ClothingDecorator{
@Override
public void Decorator(Person person) {
super.Decorator(person);
}
@Override
public void showDress() {
person.showDress();
System.out.println("衬衫");
}
}
创建一个牛仔裤类继承自穿着父类
public class JeansDecorator extends ClothingDecorator{
@Override
public void Decorator(Person person) {
super.Decorator(person);
}
@Override
public void showDress() {
super.showDress();
System.out.println("牛仔裤");
}
}
创建男人类继承自人类父类并实现人类接口
public class Man extends Human implements Person{
private String manSpecial;
public Man() {
}
public Man(String name, String age, String manSpecial) {
super(name, age);
this.manSpecial = manSpecial;
}
public String getManSpecial() {
return manSpecial;
}
public void setManSpecial(String manSpecial) {
this.manSpecial = manSpecial;
}
@Override
public void showDress() {
System.out.println("男性装扮的"+this.getName());
}
}
创建女人类继承自人类父类并实现人类接口
public class Woman extends Human implements Person{
private String womanSpecial;
public Woman() {
}
public Woman(String name, String age, String womanSpecial) {
super(name, age);
this.womanSpecial = womanSpecial;
}
public String getWomanSpecial() {
return womanSpecial;
}
public void setWomanSpecial(String womanSpecial) {
this.womanSpecial = womanSpecial;
}
@Override
public void showDress() {
System.out.println("女性装扮的"+this.getName());
}
}
具体调用
public class Main {
public static void main(String[] args) {
Person zhangSan = new Man("zhangSan","21","18");
ShirtDecorator shirt = new ShirtDecorator();
JeansDecorator jeans = new JeansDecorator();
jeans.Decorator(zhangSan);
shirt.Decorator(jeans);
shirt.showDress();
}
}
具体使用,在加密数据,过滤词汇在数据持久化之前,可以考虑将此类过程改为装饰模式。
3.代理模式
代理模式,为其他对象提供一种代理以控制对这个对象的访问。
定义Subject接口
public interface Subject {
void realProxy();
}
RealSubject 实现 Subject 接口
public class RealSubject implements Subject{
@Override
public void realProxy() {
System.out.println("real method to do something...");
}
}
Proxy 实现 Subject 接口作为代理
public class Proxy implements Subject{
private RealSubject realSubject ;
public Proxy() {
}
public Proxy(RealSubject realSubject) {
this.realSubject = realSubject;
}
@Override
public void realProxy() {
System.out.println("execute init method");
realSubject.realProxy();
System.out.println("execute destroy method");
}
}
具体调用
public class Main {
public static void main(String[] args) {
RealSubject zhuo = new RealSubject();
Proxy dali = new Proxy(zhuo);
dali.realProxy();
}
}
4.外观模式
外观模式,为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
定义三个子系统类
public class SubSystemOne {
public void method1(){
System.out.println("逻辑");
}
}
public class SubSystemTwo {
public void method2(){
System.out.println("判断");
}
}
public class SubSystemThree {
public void method3(){
System.out.println("循环");
}
}
创建外观模式外层,创建子系统类对象,提供调用方法
public class Facade {
SubSystemOne subSystemOne;
SubSystemTwo subSystemTwo;
SubSystemThree subSystemThree;
public Facade() {
subSystemOne = new SubSystemOne();
subSystemTwo = new SubSystemTwo();
subSystemThree = new SubSystemThree();
}
public void methodA(){
subSystemTwo.method2();
subSystemOne.method1();
}
public void methodB(){
subSystemTwo.method2();
subSystemThree.method3();
}
}
实际调用
public class Main {
public static void main(String[] args) {
Facade facade = new Facade();
facade.methodA();
facade.methodB();
}
}
5.桥接模式
6.组合模式
7.享元模式
四、行为型模式
1.策略模式
策略模式,定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。
Strategy 策略类接口
/**
* 策略模式 销售策略接口
*/
public abstract class SaleStrategyInterface {
//价格
private double price ;
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
//促销策略方法
public abstract double SaleStrategy();
}
多种具体的策略实现
/**
* 促销方式 - 打折
*/
public class SaleStrategyDiscount extends SaleStrategyInterface {
//折扣 percent = 1 不打折
private double percent = 1;
public SaleStrategyDiscount() {
}
public SaleStrategyDiscount(double percent) {
this.percent = percent;
}
public double getPercent() {
return percent;
}
public void setPercent(double percent) {
this.percent = percent;
}
@Override
public double SaleStrategy() {
return this.getPrice()*this.getPercent();
}
}
public class SaleStrategyFullReduction extends SaleStrategyInterface{
//满 floor 给予 减价
private double floor ;
private double sub = 0;
public SaleStrategyFullReduction() {
}
public SaleStrategyFullReduction(double floor, double sub) {
this.floor = floor;
this.sub = sub;
}
public double getFloor() {
return floor;
}
public void setFloor(double floor) {
this.floor = floor;
}
public double getSub() {
return sub;
}
public void setSub(double sub) {
this.sub = sub;
}
@Override
public double SaleStrategy() {
return this.getPrice() >= this.getFloor() ? this.getPrice() - this.sub : this.getPrice();
}
}
public class SaleStrategyPointDeduction extends SaleStrategyInterface {
//积分
private int point = 0;
//抵扣比 0为不抵扣 0.1为一积分抵扣0.1元
private double ratio = 0;
//最高抵扣多少元
private double subMax = 0;
public SaleStrategyPointDeduction() {
}
public SaleStrategyPointDeduction(double ratio, double subMax) {
this.ratio = ratio;
this.subMax = subMax;
}
public int getPoint() {
return point;
}
public void setPoint(int point) {
this.point = point;
}
public double getRatio() {
return ratio;
}
public void setRatio(double ratio) {
this.ratio = ratio;
}
public double getSubMax() {
return subMax;
}
public void setSubMax(double subMax) {
this.subMax = subMax;
}
@Override
public double SaleStrategy() {
double sub = this.getPoint() * this.getRatio();
if(sub>subMax){
this.setPoint((int)((sub-subMax)/ratio+0.5));
return this.getPrice() - this.subMax;
}else{
return this.getPrice() - sub;
}
}
}
通过简单工厂模式来实现上下文
//通过简单工厂做上下文
public class SaleContext {
SaleStrategyInterface ssi = null;
public SaleContext(String type) {
if ("全场八折".equals(type)) {
this.ssi = new SaleStrategyDiscount(0.8);
} else if ("满300减35".equals(type)) {
this.ssi = new SaleStrategyFullReduction(300, 35);
} else if ("每积分抵扣0.4,最高抵扣50元".equals(type)) {
this.ssi = new SaleStrategyPointDeduction(0.4, 50);
}else{
return;
}
}
}
实际调用
public class Main {
public static void main(String[] args) {
SaleContext saleContext = new SaleContext("全场八折");
SaleStrategyInterface saleStrategyInterface = saleContext.ssi;
saleStrategyInterface.setPrice(500);
System.out.println(saleStrategyInterface.SaleStrategy());
}
}
2.模板方法模式
模版方法模式,定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模版方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
定义模版抽象类
public abstract class AbstractClass {
//模版
public String doSomethings(int var){
int a = 12;
a = forAdd(a);
String str = new String(String.valueOf(a));
str = append(" k : " + str + "li si");
return str;
}
abstract int forAdd(int a);
abstract String append(String s);
}
实现类一
public class ConcreteClass1 extends AbstractClass{
@Override
int forAdd(int a) {
int sum = 0;
for (int i = 0; i < a; i++) {
sum += i;
}
return sum;
}
@Override
String append(String s) {
int j = s.length()-1;
for (int i = 0; i < s.length(); i++) {
char tmpl = s.charAt(i);
s.replaceAll(" ",String.valueOf(tmpl));
}
return s;
}
}
实现类二
public class ConcreteClass2 extends AbstractClass {
@Override
int forAdd(int a) {
for (int i = 0; i < a; i++) {
a += 2;
}
return a;
}
@Override
String append(String s) {
s.trim();
return s.split("1")[0];
}
}
实际调用
public class Main {
public static void main(String[] args) {
AbstractClass abstractClass1 = new ConcreteClass1();
AbstractClass abstractClass2 = new ConcreteClass2();
System.out.println(abstractClass1.doSomethings(12));
System.out.println(abstractClass2.doSomethings(12));
}
}
模版方法通过把不变行为搬移到超类,去除子类中的重复代码,提供了一个代码复用平台。
一般来说,当不变的和可变的行为在方法的子类实现中混合在一起的时候,不变的行为就会在子类中重复出现。我们通过模版方法模式把这些行为搬移到单一的地方,这样可以帮助子类办妥重复的不变行为。
3.观察者模式
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时间挺某一个主题对象。这个主体对象在状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己。
抽象观察者接口
public interface Observer {
void update();
}
抽象主题类
public class Subject {
private List<Observer> observers = new LinkedList<>();
public void attach(Observer observer){
observers.add(observer);
}
public void detach(Observer observer){
observers.remove(observer);
}
public void notifyAllOb(){
for (Observer observer : observers) {
observer.update();
}
}
}
具体主题实现类/子类
public class ConcreteSubject extends Subject{
private String subjectState;
public ConcreteSubject() {
}
public ConcreteSubject(String subjectState) {
this.subjectState = subjectState;
}
public String getSubjectState() {
return subjectState;
}
public void setSubjectState(String subjectState) {
this.subjectState = subjectState;
}
}
具体的观察者实现类
public class ConcreteObserver implements Observer{
private String name ;
private String observerState;
private ConcreteSubject concreteSubject;
public ConcreteObserver(String name, ConcreteSubject concreteSubject) {
this.name = name;
this.concreteSubject = concreteSubject;
}
@Override
public void update() {
observerState = concreteSubject.getSubjectState();
System.out.println("观察者"+name+"的新状态是"+observerState);
}
public ConcreteSubject getConcreteSubject() {
return concreteSubject;
}
public void setConcreteSubject(ConcreteSubject concreteSubject) {
this.concreteSubject = concreteSubject;
}
}
具体调用
public class Main {
public static void main(String[] args) {
ConcreteSubject s = new ConcreteSubject();
s.attach(new ConcreteObserver("x",s));
s.attach(new ConcreteObserver("y",s));
s.attach(new ConcreteObserver("z",s));
s.setSubjectState("ABC");
s.notifyAllOb();
}
}
4.迭代子模式
5.责任链模式
6.命令模式
7.备忘录模式
备忘录模式:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将该对象恢复到原先保存的状态。
以游戏中存储战斗状态为例:
把角色类作为 Originator 类。
public class Originator {
private String name; //角色名
private int hp ; //生命值
private int atk ; //攻击力
private int def ; //防御力
private int es ; //护盾
public Originator() {
}
public Originator(String name) {
this.name = name;
this.hp = 8000;
this.atk = 6000;
this.def = 4000;
this.es = 3000;
}
public Originator(String name, int hp, int atk, int def, int es) {
this.name = name;
this.hp = hp;
this.atk = atk;
this.def = def;
this.es = es;
}
public void fight(){
this.hp = hp - (int) (8000.0 * Math.random());
this.atk = atk - (int) (2000.0 * Math.random());
this.def = def;
this.es = es - 2000;
}
public void showInfo(){
System.out.println(name+" vitality: "+this.hp);
System.out.println(name+" aggressivity: "+this.atk);
System.out.println(name+" Defense capability: "+this.def);
System.out.println(name+" Shield: "+this.es);
}
public Memento saveState(){
return new Memento(this.name,this.hp,this.atk,this.def,this.es);
}
public void recoveryState(Memento memento){
this.name = memento.getName();
this.hp = memento.getHp();
this.atk = memento.getAtk();
this.def = memento.getDef();
this.es = memento.getEs();
}
}
Memento 用作存储
public class Memento {
private String name; //角色名
private int hp ; //生命值
private int atk ; //攻击力
private int def ; //防御力
private int es ; //护盾
public Memento() {
}
public Memento(String name, int hp, int atk, int def, int es) {
this.name = name;
this.hp = hp;
this.atk = atk;
this.def = def;
this.es = es;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getHp() {
return hp;
}
public void setHp(int hp) {
this.hp = hp;
}
public int getAtk() {
return atk;
}
public void setAtk(int atk) {
this.atk = atk;
}
public int getDef() {
return def;
}
public void setDef(int def) {
this.def = def;
}
public int getEs() {
return es;
}
public void setEs(int es) {
this.es = es;
}
}
Caretaker 保存 Memento
public class Caretaker {
private Memento memento;
public Memento getMemento() {
return memento;
}
public void setMemento(Memento memento) {
this.memento = memento;
}
}
实际运行:
public class Main {
public static void main(String[] args) {
//状态初始化
Originator lisi = new Originator("lisi");
lisi.showInfo();
//保存状态
Caretaker stateNow = new Caretaker();
stateNow.setMemento(lisi.saveState());
//战斗状态衰减
lisi.fight();
lisi.showInfo();
//恢复到战斗前
lisi.recoveryState(stateNow.getMemento());
lisi.showInfo();
}
}
执行结果:
IdeaProjects\demo\out\production\demo designMode.MementoPattern.Main
lisi vitality: 8000
lisi aggressivity: 6000
lisi Defense capability: 4000
lisi Shield: 3000
lisi vitality: 149
lisi aggressivity: 4721
lisi Defense capability: 4000
lisi Shield: 1000
lisi vitality: 8000
lisi aggressivity: 6000
lisi Defense capability: 4000
lisi Shield: 3000
备忘录模式比较适用于功能比较复杂的,但是需要维护或记录属性历史的类,或者需要保存的属性只是众多属性中的一小部分时,Originator 可以根据保存的 Memento 信息还原到前一状态。当在某个系统中使用命令模式时,需要实现命令的撤销功能,那么命令模式可以用备忘录模式来存储操作的状态。有事一些对象的内部信息必须保存都在对象以外的地方,但是必须要由对象自己读取,这时,备忘录可以把复杂的对象内部信息对其他的对象屏蔽起来,从而可以恰当地保存封装的边界。
8.状态模式
状态模式,当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
创建抽象父类State
public abstract class State {
int semaphore ;
abstract void handle(Context context);
}
创建上下文
public class Context {
private State state ;
public Context(State state) {
this.state = state;
}
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
System.out.println(state.getClass().toString());
}
public void request() {
state.handle(this);
}
}
设置三个状态类,并使它们继承抽象父类State
public class ConcreteStateA extends State{
@Override
void handle(Context context) {
//定义下一状态
context.setState(new ConcreteStateB());
}
}
public class ConcreteStateB extends State{
@Override
void handle(Context context) {
//定义下一状态
context.setState(new ConcreteStateC());
}
}
public class ConcreteStateC extends State{
@Override
void handle(Context context) {
//定义下一状态
context.setState(new ConcreteStateA());
}
}
实际调用
public class Main {
public static void main(String[] args) {
//设置初始状态
Context context = new Context(new ConcreteStateA());
context.request();
context.request();
context.request();
context.request();
}
}
9.访问者模式
访问者模式,表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
Visitor接口
public interface Visitor {
public abstract void visitConcreteElementA(ConcreteElementA concreteElementA);
public abstract void visitConcreteElementB(ConcreteElementB concreteElementB);
}
Element接口
public interface Element {
public abstract void accept(Visitor visitor);
}
ObjectStructure
public class ObjectStructure {
private List<Element> elements = new LinkedList<>();
public void attach(Element element){
elements.add(element);
}
public void detach(Element element){
elements.remove(element);
}
public void accept(Visitor visitor){
for (Element element : elements) {
element.accept(visitor);
}
}
}
Visitor的实现类
public class ConcreteVisitorA implements Visitor{
@Override
public void visitConcreteElementA(ConcreteElementA concreteElementA) {
System.out.println(concreteElementA.getClass().toString() + "被" + this.getClass().toString() +"访问");
}
@Override
public void visitConcreteElementB(ConcreteElementB concreteElementB) {
System.out.println(concreteElementB.getClass().toString() + "被" + this.getClass().toString() +"访问");
}
}
public class ConcreteVisitorB implements Visitor{
@Override
public void visitConcreteElementA(ConcreteElementA concreteElementA) {
}
@Override
public void visitConcreteElementB(ConcreteElementB concreteElementB) {
}
}
Element的实现类
public class ConcreteElementA implements Element{
@Override
public void accept(Visitor visitor) {
//双分派技术
visitor.visitConcreteElementA(this);
}
}
public class ConcreteElementB implements Element{
@Override
public void accept(Visitor visitor) {
visitor.visitConcreteElementB(this);
}
}
实际调用
public class Main {
public static void main(String[] args) {
ObjectStructure o = new ObjectStructure();
o.attach(new ConcreteElementA());
o.attach(new ConcreteElementB());
Visitor v1 = new ConcreteVisitorA();
Visitor v2 = new ConcreteVisitorB();
o.accept(v1);
o.accept(v2);
}
}
访问者模式适用于数据结构相对稳定的系统,他把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由地演化。
访问者模式的优点就是增加新的操作很容易,因为增加新的操作就意味着增加一个新的访问者。访问者模式将有关的行为集合到一个访问者对象中,缺点就是增加新的数据结构变得十分困难。