介绍:相对于工厂模式,不将具体的类暴露给调用者,而是在工厂中判断需要哪个类,则提供调用该类的方法给调用者。
应用场景:
介绍:类的功能尽量单一,也就是活字印刷将文章划分成单一的字,而不是词的原因。
划分原则:应该仅有一个引起它变化的原因。
应用:类的功能设计尽量单一。
介绍:对修改关闭,对扩展开放。
实现方式:通过接口或抽象类的继承,通过不同子类应对变化。如下图。
介绍:A:高层模块不应该依赖低层模块。两个都应该依赖抽象。B:抽象不应该依赖细节。细节应该依赖抽象。
应用场景:也就是面向接口和抽象编程。
介绍:子类型必须能够替换掉他们的父类型。
应用场景:在扩展时,只需要替换即可完成,无需修改其他子类和父类代码。
介绍:装饰模式,动态地给一个对象添加一些额外的职责,就功能来说,装饰模式比生成子类更为灵活。
实现方式:通过编写一个抽象类,子类构造方法中传入需要装饰的父类,并实现父类的方法,对其进行装饰。
// 装饰接口
public interface Decorator {
void operation();
}
// 具体装饰A
class ConcreteDecoratorA implements Decorator{
private String addedState = "add state";
private Decorator decorator;
public ConcreteDecoratorA(Decorator decorator) {
this.decorator = decorator;
}
@Override
public void operation() {
// 加入状态装饰
System.out.println(addedState);
decorator.operation();
}
}
// 具体装饰B
class ConcreteDecoratorB implements Decorator{
private Decorator decorator;
public ConcreteDecoratorB(Decorator decorator) {
this.decorator = decorator;
}
private void addedBehavior(){
System.out.println("add Behavior");
}
@Override
public void operation() {
decorator.operation();
// 加入行为装饰
addedBehavior();
}
}
// 客户端
class Client {
public static void main(String[] args) {
// 未加装饰的基础对象
Decorator decorator = new Decorator() {
@Override
public void operation() {
System.out.println("base operation!!!");
}
};
Decorator decoratorB = new ConcreteDecoratorB(decorator);
Decorator decoratorA = new ConcreteDecoratorA(decoratorB);
decoratorA.operation();
}
}
介绍:代理模式是为其他对象提供一种代理以控制对这个对象的访问,从而可以在不改变原有类的基础上,在这个类的各个方法的前后各切面上加入新增的功能方法。
实现方式:
// 代理
public class NoamalProxy {
private PersonDao personDao;
private Trancation trancation;
public NoamalProxy(PersonDao personDao, Trancation trancation) {
this.personDao = personDao;
this.trancation = trancation;
}
public void savePerson() {
// 开启事务
trancation.beginTrancation();
// 保存人员
personDao.savePerson();
// 提交事务
trancation.commit();
}
}
// 人员DAO
class PersonDao {
public void savePerson() {
System.out.println("保存人员");
}
}
// 事务
class Trancation {
public void beginTrancation() {
System.out.println("开启事务");
}
public void commit() {
System.out.println("提交事务");
}
}
// 客户端
class Client {
public static void main(String[] args) {
NoamalProxy proxy = new NoamalProxy(new PersonDao(),new Trancation());
proxy.savePerson();
}
}
- jdk代理:创建一个接口和一个实现类,以及一个实现了InvocationHandler的实现类,重写invoke方法,则在代理对象调用时,会调用该方法。
// jdk代理
public class JdkProxy implements InvocationHandler{
private Trancation2 trancation;
private PersonDao2 target;
public JdkProxy(Trancation2 trancation, PersonDao2 target) {
this.trancation = trancation;
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 开启事务
trancation.beginTrancation();
// 方法调用,注!!!此处传入的Object为代理,而不是目标类,目标类需要另外注入
Object obj = method.invoke(target, args);
// 开启事务
trancation.commit();
return obj;
}
}
// jdk的代理需要实现接口
interface PersonDao2{
void savePerson();
}
// 人员DAO
class PersonDaoImpl2 implements PersonDao2{
@Override
public void savePerson() {
System.out.println("保存人员");
}
}
// 事务
class Trancation2 {
public void beginTrancation() {
System.out.println("开启事务");
}
public void commit() {
System.out.println("提交事务");
}
}
// 客户端
class Client2 {
public static void main(String[] args) {
Trancation2 t2 = new Trancation2();
PersonDao2 p2 = new PersonDaoImpl2();
JdkProxy jdkProxy = new JdkProxy(t2,p2);
PersonDao2 dao2 = (PersonDao2) Proxy.newProxyInstance(p2.getClass().getClassLoader(),p2.getClass().getInterfaces(),jdkProxy);
dao2.savePerson();
}
}
- cglib代理:创建一个类,以及一个实现了MethodInterceptor的实现类,重写intercept方法,则在代理对象调用时,会调用该方法,并初始化Enhancer类,该对象可创建代理对象。
// cglib代理
public class CglibProxy implements MethodInterceptor{
private Trancation3 trancation;
private PersonDao3 target;
public CglibProxy(Trancation3 trancation, PersonDao3 target) {
this.trancation = trancation;
this.target = target;
}
// 创建代理
public Object createProxy() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
// 开启事务
trancation.beginTrancation();
// 方法调用,注!!!此处传入的Object为代理,而不是目标类,目标类需要另外注入
Object obj = method.invoke(target, objects);
// 提交事务
trancation.commit();
return obj;
}
}
// 人员DAO
class PersonDao3 implements PersonDao2{
@Override
public void savePerson() {
System.out.println("保存人员");
}
}
// 事务
class Trancation3 {
public void beginTrancation() {
System.out.println("开启事务");
}
public void commit() {
System.out.println("提交事务");
}
}
// 客户端
class Client3 {
public static void main(String[] args) {
Trancation3 t3 = new Trancation3();
PersonDao3 p3 = new PersonDao3();
CglibProxy cglibProxy = new CglibProxy(t3,p3);
PersonDao3 personDao3 = (PersonDao3) cglibProxy.createProxy();
personDao3.savePerson();
}
}
介绍:工厂模式为用户在切换使用对象时可通过配置文件加反射的方式,选择需要创建的对象。
实现方式:创建工厂接口和对象的工厂类,创建具体类和抽象类,通过工厂类进行初始化。其中对工厂的抽象化是为了在客户端可以方便地扩展工厂。
// 工厂接口
public interface Factory {
Animal createAnimal();
}
// 动物抽象类
abstract class Animal{
abstract void eat();
}
// 狗
class Dog extends Animal{
@Override
void eat() {
System.out.println("狗啃骨头");
}
}
// 猫
class Cat extends Animal{
@Override
void eat() {
System.out.println("猫吃鱼");
}
}
// 狗工厂
class DogFactory implements Factory{
@Override
public Animal createAnimal() {
return new Dog();
}
}
// 猫工厂
class CatFactory implements Factory{
@Override
public Animal createAnimal() {
return new Cat();
}
}
// 客户端
class Client{
public static void main(String[] args) {
Factory catFactory = new CatFactory();
Animal cat = catFactory.createAnimal();
Factory dogFactory = new DogFactory();
Animal dog = dogFactory.createAnimal();
cat.eat();
dog.eat();
}
}
-介绍:实际就是对对象数据的复制,浅复制指只对对象的基本类型复制,引用类型只复制引用,而深复制会把引用类型的数据进行复制;
-实现方式:通过在实体上实现Cloneable接口,并重写clone()方法进行实现。代码如下:
public class CloneTest implements Cloneable {
private String name;
private City city;
@Override
public CloneTest clone() {
CloneTest cloneTest = null;
try {
// 浅复制——只复制该对象的基本类型数据
cloneTest = (CloneTest) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
// 对引用的数据进行复制为深度复制
cloneTest.city = city.clone();
return cloneTest;
}
}
应用场景:需要用到对象的大部分数据,并进行小部分修改,又不想影响原有对象的情况。
注意:
1. clone()方法不依赖于get/set方法;
2. 实体不实现Cloneable接口的情况下,调用父类的clone()方法,会报CloneNotSupportedException的异常;
介绍:模板设计模式是提供一个顶级的逻辑骨架,逻辑中具体的步骤在抽象方法中,推迟到子类实现。从而能够将大部分相同的逻辑抽象到父类方法中,具体小的细节由子类进行实现。
实现方式:在父类中定义一个具体方法,该方法调用该类的抽象方法,由子类实现具体的抽象方法,最后调用该类的具体方法。如下图:
public abstract class TestTemplate {
public void templateMethod() {
System.out.println("我需要获取person表中的数据");
selectPerson();
}
public abstract void selectPerson();
public static void main(String[] args) {
TestTemplate testTemplate = new TestTemplate() {
@Override
public void selectPerson() {
System.out.println("通过postgresql数据库获取person数据 name:'sean' age:12");
}
};
testTemplate.templateMethod();
}
}
介绍:通过统一的接口(人),对类之间的调用进行解耦操作。
实现方式:两个类之间不必彼此直接通信时,两个类可通过第三者转发这个调用。
介绍:是对多个类的复杂逻辑的同一封装,也就是上述迪米特法则的统一实现。
应用场景:存在复杂的下层逻辑和多个下层对象,但上层可整理出规范的接口。
介绍:该模式与模板模式类似,都是提供一个逻辑的骨架,而骨架中的具体实现则交由实现类完成,与模板模式的区别在于将构建过程从模板类中移至指挥类中,从而使得建造者类可以没有具体方法,成为接口。
实现方式:见下图和代码。
//建造者接口
public interface Builder {
// 添加第一部分
void addPart1();
// 添加第二部分
void addPart2();
// 获得产品
Product getProduct();
}
// 产品
class Product {
private List parts = new ArrayList<>();
// 添加部分
public void add(String s) {
parts.add(s);
}
// 展示产品
public void show() {
System.out.println(parts);
}
}
// 指挥者
class Director {
public void construct(Builder builder) {
builder.addPart1();
builder.addPart2();
}
public static void main(String[] args) {
Director director = new Director();
// 创建具体的构造者
Builder b1 = new Builder() {
private Product product = new Product();
@Override
public void addPart1() {
product.add("X");
}
@Override
public void addPart2() {
product.add("Y");
}
@Override
public Product getProduct() {
return product;
}
};
director.construct(b1);
// 创建具体的构造者
Builder b2 = new Builder() {
private Product product = new Product();
@Override
public void addPart1() {
product.add("A");
}
@Override
public void addPart2() {
product.add("B");
}
@Override
public Product getProduct() {
return product;
}
};
director.construct(b2);
Product product1 = b1.getProduct();
Product product2 = b2.getProduct();
product1.show();
product2.show();
}
}
介绍:一个事件产生后,需要得知此事件的对象都需要进行相应的相应的过程。
实现方式:实际是对事件和监听者之间的解耦。
// 事件
public class Event1 {
private List listensers = new ArrayList<>();
public void addListenser(Listenser listenser) {
listensers.add(listenser);
}
public void handEvent() {
for (Listenser listenser : listensers) {
if (listenser == null) {
continue;
}
listenser.onEvent();
}
}
}
interface Listenser {
void onEvent();
}
// 监听器A
class ListenserA implements Listenser {
@Override
public void onEvent() {
System.out.println("listenser A!");
}
}
// 监听器B
class ListenserB implements Listenser {
@Override
public void onEvent() {
System.out.println("listenser B!");
}
}
// 客户端
class Client{
public static void main(String[] args) {
Listenser la = new ListenserA();
Listenser lb = new ListenserB();
Event1 event = new Event1();
event.addListenser(la);
event.addListenser(lb);
event.handEvent();
}
}
2. 事件属性中加入一个观察者对象,其中包括观察者对象,观察者需要调用的方法名和方法的参数数组;
public class Event2 {
private List listenserDtos = new ArrayList<>();
public void addListenser(ListenserDto listenserDto) {
listenserDtos.add(listenserDto);
}
public void handEvent() {
if (listenserDtos != null && listenserDtos.size() > 0) {
for (ListenserDto listenserDto : listenserDtos) {
if (listenserDto == null) {
continue;
}
try {
// 通过反射调用方法
Method method = listenserDto.getObj().getClass().getMethod(listenserDto.getMethodNamd(), listenserDto.getArgTypes());
method.invoke(listenserDto.getObj(), listenserDto.getArgs());
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
// 监听对象方法及参数的DTO
class ListenserDto {
private Object obj;
private String methodNamd;
private Object[] args;
private Class[] argTypes;
public Object getObj() {
return obj;
}
public String getMethodNamd() {
return methodNamd;
}
public Object[] getArgs() {
return args;
}
public Class[] getArgTypes() {
return argTypes;
}
public ListenserDto(Object obj, String methodNamd, Object[] args) {
this.obj = obj;
this.methodNamd = methodNamd;
this.args = args;
if (args != null && args.length > 0) {
this.argTypes = new Class[args.length];
for (int i = 0; i < args.length; i++) {
argTypes[i] = args[i].getClass();
}
}
}
}
class Listenser2A {
public void methodA(String name, Integer age) {
System.out.println("A " + name + " -- " + age);
}
}
class Listenser2B {
public void methodB(String name) {
System.out.println("B " + name);
}
}
class Client2 {
public static void main(String[] args) {
Event2 event2 = new Event2();
// 将监听者及方法和参数放入事件中
event2.addListenser(new ListenserDto(new Listenser2A(),"methodA",new Object[]{"sean",22}));
event2.addListenser(new ListenserDto(new Listenser2B(),"methodB",new Object[]{"tan"}));
event2.handEvent();
}
}
3. 事件的构造方法中加入观察者的接口类型,在调用事件发布方法时,遍历观察者接口的所有容器中的实体,并调用统一的接口方法;
@Component
public class Event3 {
private Class listenserClass;
public Event3() {
this.listenserClass = Listenser3.class;
}
public void sendNotify(){
// 通过类型获取容器中的监听者,进行方法调用
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Map beansMap = context.getBeansOfType(listenserClass);
Collection beans = beansMap.values();
if (beans != null && beans.size() > 0) {
for (Object bean : beans) {
Listenser3 li = (Listenser3)bean;
li.onEvent(this);
}
}
}
}
interface Listenser3{
void onEvent(Event3 event3);
}
@Service
class Listenser3A implements Listenser3{
@Override
public void onEvent(Event3 event3) {
System.out.println("listenser3A "+event3);
}
}
@Service
class Listenser3B implements Listenser3{
@Override
public void onEvent(Event3 event3) {
System.out.println("listenser3B "+event3);
}
}
class Client{
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Event3 event3 = (Event3) context.getBean("event3");
event3.sendNotify();
}
}
4. 通过spring实现,观察者中加入事件的泛型,在调用事件发布方法时,通过含有泛型的观察者接口的所有容器中的实体,并调用统一的接口方法;
@Component
public class Event4 extends ApplicationEvent{
public Event4(){
super("ss");
}
public Event4(Object source) {
super(source);
}
public void sendNotify(){
// 通过容器发布事件,实际会根据监听者的泛型找到监听者,并调用onApplicationEvent方法
new ClassPathXmlApplicationContext("applicationContext.xml").publishEvent(this);
}
}
@Component
class Listenser4A implements ApplicationListener<Event4> {
@Override
public void onApplicationEvent(Event4 event4) {
System.out.println("Listenser4A " +event4);
}
}
class Client4{
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Event4 event4 = (Event4) context.getBean("event4");
event4.sendNotify();
}
}
介绍:用户需要什么,工厂就生成创建什么,解除了客户端对具体对象的依赖,而交由工厂中的反射获取配置文件中具体需要哪种类型。
实现方式:创建一个工厂,由工厂根据配置调用反射创建需要创建的对象,在客户端调用该工厂获取需要的对象即可:
// 数据库工厂
public class DBFactory {
// 此处可通过配置文件读取
private static String dbName = "MySql";
public static DB createDB(){
try {
// 通过反射进行解耦,创建实体
return (DB) Class.forName("com.sean.design.a14_factory."+dbName + "DB").newInstance();
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
// 数据库
interface DB{
void save();
}
// MySql数据库
class MySqlDB implements DB{
@Override
public void save() {
System.out.println("MySql save");
}
}
// Postgresql数据库
class PostgresqlDB implements DB{
@Override
public void save() {
System.out.println("Postgresql save");
}
}
class Client{
public static void main(String[] args) {
DB db = DBFactory.createDB();
db.save();
}
}
介绍:为了消除庞大的条件分支语句,通过把各种状态转移逻辑分布到 State 的子类之间,来减少相互间的依赖。
实现方式:通过一个Context来调用 State 状态的处理方法,而 State 状态的处理方法中除了状态的处理方法外,还有根据条件进行状态切换的逻辑。
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;
}
// 逻辑处理
public void request(){
state.handle(this);
}
}
// 状态接口
interface State{
void handle(Context context);
}
// 具体状态A
class StateA implements State{
@Override
public void handle(Context context) {
// 逻辑处理
System.out.println("this is state A");
// 状态切换
context.setState(new StateB());
}
}
// 具体状态B
class StateB implements State{
@Override
public void handle(Context context) {
// 逻辑处理
System.out.println("this is state B");
// 状态切换
context.setState(new StateA());
}
}
class client{
public static void main(String[] args) {
Context context = new Context(new StateA());
context.request();
context.request();
context.request();
}
}
介绍:适配器模式主要作用是对已经无法改变或难以改变的接口进行再次包装,以便调用进行适配。
实现方式:在需要适配的接口上再加上一层接口进行包装。
// 适配器
public class Adapter implements MyTarget{
private NeedAdapter needAdapter = new NeedAdapter();
@Override
public void test3(){
needAdapter.test1();
}
}
// 统一的接口
interface MyTarget{
void test3();
}
// 需要适配的类
class NeedAdapter{
public void test1(){
System.out.println("test1");
}
public void test2(){
System.out.println("test2");
}
}
// 客户端
class Client{
public static void main(String[] args) {
MyTarget target = new Adapter();
target.test3();
}
}
介绍:备忘录模式更像一种场景,需要备份一个对象的模式,用对象本身克隆存在有不需要备份的字段也会备份,不够灵活的问题。而备忘录模式是将数据备份的读和写交由第三方来实现,更加灵活,解耦。
实现方式:将本对象的值交由另一备忘录对象存储管理,本对象只需要实现获取备忘录对象和恢复备忘录对象的值,而具体需要备份和恢复哪些值则交由备忘录对象来决定,从而进行解耦。
public class GamePlayer {
private String name;// 姓名
private int attack;// 攻击力
private int defense;// 防御力
// 创建备忘录
public Memo getMemo(){
return new Memo(this);
}
// 还原备忘录
public void recoverMemo(Memo memo){
memo.recover(this);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAttack() {
return attack;
}
public void setAttack(int attack) {
this.attack = attack;
}
public int getDefense() {
return defense;
}
public void setDefense(int defense) {
this.defense = defense;
}
@Override
public String toString() {
return "GamePlayer{" +
"name='" + name + '\'' +
", attack=" + attack +
", defense=" + defense +
'}';
}
}
// 备忘录
class Memo{
private int attack;
private int defense;
// 创建备忘录
public Memo(GamePlayer gamePlayer){
this.attack = gamePlayer.getAttack();
this.defense = gamePlayer.getDefense();
}
// 恢复备忘录
public void recover(GamePlayer gamePlayer) {
gamePlayer.setAttack(this.attack);
gamePlayer.setDefense(this.defense);
}
}
class Client{
public static void main(String[] args) {
GamePlayer gamePlayer = new GamePlayer();
gamePlayer.setName("Sean");
gamePlayer.setAttack(100);
gamePlayer.setDefense(100);
System.out.println("战斗前");
System.out.println(gamePlayer);
Memo memo = gamePlayer.getMemo();
gamePlayer.setDefense(80);
gamePlayer.setAttack(70);
System.out.println("战斗后");
System.out.println(gamePlayer);
System.out.println("恢复到战斗前");
gamePlayer.recoverMemo(memo);
System.out.println(gamePlayer);
}
}
介绍:组合模式不像一种设计模式,更像是一种数据结构,有顶级节点,并在节点下挂有下级节点对象的一棵树,每个节点有各自的方法,且可以执行含本级节点及下级节点信息的操作。
实现方式:定义一个抽象类,然后定义一个继承抽象类的具体类,该具体类有一个抽象类的集合作为分支节点。
public abstract class Company {
private String name;
// 加入
abstract void addCompany(Company company);
abstract void removeCompany(Company company);
// 打印所有分公司部门
abstract void printLine(int depth);
// 履行职责
abstract void lineOfDuty();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
// 分公司
class ConcreteCompany extends Company{
private List companies = new ArrayList<>();
@Override
void addCompany(Company company) {
companies.add(company);
}
@Override
void removeCompany(Company company) {
companies.remove(company);
}
@Override
void printLine(int depth) {
for (int i = 0;i"-");
}
System.out.println(this.getName());
if (companies != null && companies.size() > 0) {
for (Company company : companies) {
if (company == null) {
continue;
}
company.printLine(depth+2);
}
}
}
@Override
void lineOfDuty() {
if (companies != null && companies.size() > 0) {
for (Company company : companies) {
if (company == null) {
continue;
}
company.lineOfDuty();
}
}
}
}
// HR部门
class HRDepartment extends Company{
@Override
void addCompany(Company company) {}
@Override
void removeCompany(Company company) {}
@Override
void printLine(int depth) {
for (int i = 0;i"-");
}
System.out.println(this.getName());
}
@Override
void lineOfDuty() {
System.out.println(this.getName()+"负责招聘");
}
}
class Client{
public static void main(String[] args) {
Company root = new ConcreteCompany();
root.setName("北京总公司");
HRDepartment rootDepartment = new HRDepartment();
rootDepartment.setName("北京HR部门");
root.addCompany(rootDepartment);
Company hangZhou = new ConcreteCompany();
hangZhou.setName("杭州分公司");
HRDepartment hangZhouDepartment = new HRDepartment();
hangZhouDepartment.setName("杭州HR部门");
hangZhou.addCompany(hangZhouDepartment);
root.addCompany(hangZhou);
Company nanJing = new ConcreteCompany();
nanJing.setName("南京分公司");
root.addCompany(nanJing);
root.printLine(1);
System.out.println();
root.lineOfDuty();
}
}
由于java通过增强for实现该模式,故略。
介绍:单例模式也就是一个类有且只有一个实例对象,故需要对其构造方法私有化,且实例的初始化由本类进行,初始化时机的不同使单例模式分为懒汉式(在调用获取实例的静态方法中初始化)和饿汉式(在类加载时,通过静态变量进行初始化)。
实现方式:1.构造方法私有化;2.1在调用获取实例的静态方法中初始化,此处需要进行加锁,因为多线程情况会导致多实例化;2.2在类加载时,通过静态变量进行初始化
// 懒汉式,在获取实例时初始化,通过加锁避免多线程问题,消耗加锁的时间,但节约内存开销,只有在需要用到该实例时才初始化
public class LazySingleton {
private static LazySingleton lazySingleton;
private LazySingleton() {
}
public static LazySingleton getInstance(){
// 不在每次获取实例时加锁,节约资源
if (lazySingleton==null){
synchronized (LazySingleton.class){
// 可能在获取锁前已经由另一线程初始化
if (lazySingleton == null){
return new LazySingleton();
}
}
}
return lazySingleton;
}
}
// 饿汉式,在类加载时初始化,消耗内存,但避免多线程问题
class EagerSingleton{
private static EagerSingleton eagerSingleton = new EagerSingleton();
private EagerSingleton() {
}
public static EagerSingleton getInstance(){
return eagerSingleton;
}
}
介绍:桥接模式主要是基于合成/聚合复用原则(尽量使用合成/聚合,尽量不要使用集成)实现的,他将不是is a 的继承关系拆分成 has a 的关系,从而解除了强耦合,当有一个(has a)新特性时,不需要改每个实现类,只需要加一个聚合的类即可。
实现方式:将没有继承关系的类拆分成合成/聚合的关系,当有新功能时,只需要加一个合成或聚合的类即可。
// 抽象类
public abstract class Abstraction {
// 通过聚合关系进行桥接
private Implementor implementor;
// 操作桥接对象的功能方法
abstract void operation();
public Implementor getImplementor() {
return implementor;
}
public void setImplementor(Implementor implementor) {
this.implementor = implementor;
}
}
// 具体类
class RefinedAbstraction extends Abstraction{
@Override
void operation() {
this.getImplementor().operationImpl();
}
}
// 桥接抽象类
abstract class Implementor{
// 桥接类的操作
abstract void operationImpl();
}
// 具体桥接类A
class ConcreteImplementorA extends Implementor{
@Override
void operationImpl() {
System.out.println("A操作");
}
}
// 具体桥接类B
class ConcreteImplementorB extends Implementor{
@Override
void operationImpl() {
System.out.println("B操作");
}
}
// 客户端
class Client{
public static void main(String[] args) {
Abstraction abstraction = new RefinedAbstraction();
abstraction.setImplementor(new ConcreteImplementorA());
abstraction.operation();
abstraction.setImplementor(new ConcreteImplementorB());
abstraction.operation();
}
}
介绍:命令模式主要是将两个对象间的调用请求抽象成一个命令对象,从而可以对一个请求命令进行操作,如明日记入日志,否决,撤销重做,统一执行,并对调用者和接受者之间解耦,有新的命令,只需增加一个新的类即可,此处与上一个桥接模式类似,也是通过聚合的方式进行解耦。
// 命令接口
public interface Commond {
// 获取命令名称
String getName();
// 执行命令
void excute();
}
// 烤羊肉串命令
class BakeMuttonCommond implements Commond{
private Barbecuer barbecuer;
private String name = "烤羊肉串";
@Override
public String getName() {
return name;
}
public BakeMuttonCommond(Barbecuer barbecuer) {
this.barbecuer = barbecuer;
}
@Override
public void excute() {
barbecuer.bakeMutton();
}
}
// 烤鸡翅命令
class BakeChickenWingCommond implements Commond{
private Barbecuer barbecuer;
private String name = "烤鸡翅";
@Override
public String getName() {
return name;
}
public BakeChickenWingCommond(Barbecuer barbecuer) {
this.barbecuer = barbecuer;
}
@Override
public void excute() {
barbecuer.bakeChickenWing();
}
}
// 烧烤师傅
class Barbecuer{
// 烤羊肉串方法
public void bakeMutton(){
System.out.println("烤羊肉串!");
}
// 烤鸡翅方法
public void bakeChickenWing(){
System.out.println("烤鸡翅!");
}
}
// 服务员
class Water{
private List orders = new ArrayList<>();
// 增加订单
public void addOrder(Commond commond){
if (commond instanceof BakeChickenWingCommond){
System.out.println("鸡翅没有了,请点别的烧烤。");
}else {
orders.add(commond);
System.out.println("增加订单:"+commond.getName()+" 时间:"+new Date());
}
}
// 取消订单
public void concleOrder(Commond commond){
orders.remove(commond);
System.out.println("取消订单:"+commond.getName()+" 时间:"+new Date());
}
// 执行所有命令
public void notifyCommond(){
if (orders != null && orders.size() > 0) {
for (Commond order : orders) {
if (order == null) {
continue;
}
order.excute();
}
}
}
}
// 客户端
class Client{
public static void main(String[] args) {
Barbecuer barbecuer = new Barbecuer();
Commond commond1 = new BakeMuttonCommond(barbecuer);
Commond commond2 = new BakeMuttonCommond(barbecuer);
Commond commond3 = new BakeMuttonCommond(barbecuer);
Commond commond4 = new BakeChickenWingCommond(barbecuer);
Water water = new Water();
water.addOrder(commond1);
water.addOrder(commond2);
water.addOrder(commond3);
water.addOrder(commond4);
water.concleOrder(commond1);
water.notifyCommond();
}
}
介绍:职责链模式与之前的状态模式相似,都是将繁琐的条件判断语句化繁为简,抽象成一个对象,然后交由对象根据自身的职权来执行任务,或者切换到下一对象,不同之处在于职责链模式通过设置下一职责链对象,将对象间的切换交由客户端来给出,来进行切换。
实现方式:将繁琐的条件判断语句抽象成对象,由对象来进行条件判断是否能够执行该任务还是切换到下一对象进行任务执行。
// 处理接口
public abstract class Handler {
protected Handler successor;
// 设置继任者
public void setSuccessor(Handler handler) {
this.successor = handler;
}
// 处理请求
abstract void handleRequest(int request);
}
// 具体处理类A
class ConcreteHandlerA extends Handler {
@Override
public void handleRequest(int request) {
if (request<10){
System.out.println("ConcreteHandlerA 处理了 "+request+" 该请求");
}else {
// 本处理类无权限,则交由继任者处理该请求
successor.handleRequest(request);
}
}
}
// 具体处理类B
class ConcreteHandlerB extends Handler {
@Override
public void handleRequest(int request) {
if (request>=10&&request<20){
System.out.println("ConcreteHandlerB 处理了 "+request+" 该请求");
}else {
// 本处理类无权限,则交由继任者处理该请求
successor.handleRequest(request);
}
}
}
// 具体处理类C
class ConcreteHandlerC extends Handler {
@Override
public void handleRequest(int request) {
System.out.println("ConcreteHandlerC 处理了 " + request + " 该请求");
}
}
// 客户端
class Client{
public static void main(String[] args) {
Handler handlerA = new ConcreteHandlerA();
Handler handlerB = new ConcreteHandlerB();
Handler handlerC = new ConcreteHandlerC();
handlerA.setSuccessor(handlerB);
handlerB.setSuccessor(handlerC);
handlerA.handleRequest(3);
handlerA.handleRequest(12);
handlerA.handleRequest(33);
handlerA.handleRequest(25);
handlerA.handleRequest(100);
handlerA.handleRequest(-3);
}
}
介绍:中介者模式是将多个对象间的调用进行抽象成一个中介者,由中介者来控制调用对象的调用,对多个对象间的耦合关系进行解耦,但是对象较多的情况,中介者将会与多个对象进行耦合并变得复杂,尤其是对象调用间没有具体的规律的情况,在中介者中还需要增加何种情况才调用的逻辑判断,较为复杂,若没有该逻辑判断,则与职责链模式类似,故慎用或不用。
实现方式:将多个对象间的调用抽象出一个中介者,进行对象间信息交互的中间者。
介绍:享元模式可以避免大量非常相似的类的开销,实际是在对象可以共用的情况下只提供一个对象,从而减少大量实例化对象。
实现方式:将大量有重复使用的对象通过工厂类初始化,并只能获取一个对象。
// 享元接口
public abstract class Flyweight {
protected String name;
public Flyweight(String name) {
this.name = name;
}
// 操作方法
abstract void operation(int i);
}
// 共享的具体享元
class ConcreteFlyweight extends Flyweight {
public ConcreteFlyweight(String name) {
super(name);
}
@Override
public void operation(int i) {
System.out.println("具体的 "+name+" flyweight:"+i);
}
}
// 不共享的具体享元
class UnsharedConcreteFlyweight extends Flyweight{
public UnsharedConcreteFlyweight(String name) {
super(name);
}
@Override
public void operation(int i) {
System.out.println("具体的 "+name+" unsharedFlyweight:"+i);
}
}
// 享元工厂类
class FlyweightFactory{
private Map flyweights = new HashMap<>();
// 获取共享单元
public Flyweight getFlyweights(String name){
// 若不存在,则创建该享元
if (!flyweights.containsKey(name)){
flyweights.put(name, new ConcreteFlyweight(name));
}
return flyweights.get(name);
}
}
// 客户端
class Client{
public static void main(String[] args) {
int count = 10;
FlyweightFactory flyweightFactory = new FlyweightFactory();
Flyweight x = flyweightFactory.getFlyweights("X");
x.operation(--count);
Flyweight y = flyweightFactory.getFlyweights("Y");
y.operation(--count);
Flyweight z = flyweightFactory.getFlyweights("Z");
z.operation(--count);
Flyweight t = new UnsharedConcreteFlyweight("T");
t.operation(--count);
}
}
介绍:解释器模式的作用主要是对内容进行翻译,通过多个具体类对各类文法进行翻译,从而实现整篇内容得到翻译。
实现方式:通过定义一个抽象类,对需要翻译的文本内容进行接收,并翻译。
介绍:访问者模式是解决当对象种类固定,操作可扩展的情况,因操作可扩展,所以将操作进行分类,并使用继承或接口,操作类中的方法是区分对象种类的方法实现,若在操作类中的方法需要获取对象种类的数据,则参数中需要传入对象种类的参数。
实现方式:定义一个对象类的接口和具体类及方法,方法为接受操作类,并根据自身调用操作类中的方法,定义一个操作接口和具体类和方法。
// 人接口
public interface Person {
String getType();
// 接受操作
void accept(Action action);
}
// 操作接口
interface Action {
String getType();
// 做男人的操作
void doManAction(Person person);
// 做女人的操作
void doWomanAction(Person person);
}
// 男人
class Man implements Person {
@Override
public String getType() {
return "男人";
}
@Override
public void accept(Action action) {
action.doManAction(this);
}
}
// 女人
class Woman implements Person {
@Override
public String getType() {
return "女人";
}
@Override
public void accept(Action action) {
action.doWomanAction(this);
}
}
// 成功
class Success implements Action {
@Override
public String getType() {
return "成功";
}
@Override
public void doManAction(Person person) {
System.out.println(person.getType() + this.getType() + "时,背后多半有一个伟大的女人");
}
@Override
public void doWomanAction(Person person) {
System.out.println(person.getType() + this.getType() + "时,背后大多有一个不成功的男人");
}
}
// 失败
class Failing implements Action {
@Override
public String getType() {
return "失败";
}
@Override
public void doManAction(Person person) {
System.out.println(person.getType() + this.getType() + "时,闷头喝酒,谁也不用劝");
}
@Override
public void doWomanAction(Person person) {
System.out.println(person.getType() + this.getType() + "时,泪眼汪汪,谁也劝不了");
}
}
// 结构
class ObjectStruct {
private List people = new ArrayList<>();
public void addPerson(Person person) {
people.add(person);
}
// 遍历循环调用
public void doAction(Action action) {
for (Person person : people) {
if (person == null) {
continue;
}
person.accept(action);
}
}
}
// 客户端
class Client {
public static void main(String[] args) {
Person man = new Man();
Person woman = new Woman();
ObjectStruct os = new ObjectStruct();
os.addPerson(man);
os.addPerson(woman);
os.doAction(new Success());
os.doAction(new Failing());
}
}