主页 > 手机  > 

十大设计模式总结版


十大设计模式总结版 十大设计模式1.Singleton 单例模式1.1单例模式的实现思路1.2饿汉类1.2.1优点 1.3懒汉类1.3.1优点 1.4双重检查锁1.4.1优点 1.5静态内部类1.5.1优点 1.6枚举类1.6.1优点 1.7ThreadLocal1.7.1优点 2.Proxy 代理模式2.1静态代理2.1.1静态代理的实现思路2.1.2优点 2.2动态代理2.2.1动态代理的实现思路 2.3Cglib代理2.3.1Cglib代理的实现思路Cglib的maven依赖 2.3.2优点 3.Adapter适配器模式3.1类的适配器模式的实现思路(继承实现)3.2对象的适配器模式(扩展实现)3.3优点 4.Chain责任链模式4.1责任链的实现思路4.2优点 5.Simple Factory简单工厂模式5.1简单工厂的实现思路 6.Factory Method工厂方法模式6.1工厂方法的实现思路6.2优点 7.Template Method模板方法模式7.1模板方法的实现思路7.2优点 8.Decorator 装饰器模式8.1装饰器的实现思路8.2优点 9.Observer 观察者模式9.1观察者的实现思路9.2优点 10.Strategy 策略模式10.1策略模式的实现思路10.2优点

十大设计模式

主要是对前面的设计模式进行一个总结,主要掌握以下十大设计模式,其他的设计模式后面的在慢慢熟悉。

1.Singleton 单例模式 1.1单例模式的实现思路 静态化实例对象,让实例对象与Class对象互相绑定,通过Class类对象就可以直接访问私有化构造方法,禁止通过构造方法来创建多个实例创建公共的静态方法,通过该静态方法来调用私有化构造方法来创建对象,并将其保存在一个静态成员变量中,用来返回该类的唯一实例。 1.2饿汉类 public class Hungry { //1.创建一个静态实例对象 private static Hungry instance = new Hungry(); //2. 私有化构造方法 private Hungry() {} //3.在静态方法中创建实例对象,并将其返回 public static Hungry getInstance() { return instance; } } 1.2.1优点 JVM层面的线程安全造成空间的浪费 1.3懒汉类 package com.technologystatck.designpattern.modereview.singleton; public class Lazy { //1.创建一个静态实例对象,允许为空 private static Lazy instance = null; //2.私有化构造方法 private Lazy() { } //3.在静态方法中实例化对象,并将其返回 public static Lazy getInstance() { if (instance == null) { instance = new Lazy(); } return instance; } //4.若为线程安全可以使用synchronized关键字 public static synchronized Lazy getSynInstance() { if (instance == null) { instance = new Lazy(); } return instance; } } 1.3.1优点 节省空间,用到的时候再创建实例对象线程不安全若添加了synchronized关键字,对同步进行操作,有很严重的性能问题 1.4双重检查锁 package com.technologystatck.designpattern.modereview.singleton; public class DoubleCheckLocking { //1.创建实例对象 private static volatile DoubleCheckLocking instance=null; //2.私有化构造方法 private DoubleCheckLocking(){ } //3.使用静态方法中创建对象 public static DoubleCheckLocking getInstance(){ //先判断实例是否存在 if(instance == null){ //加锁创建实例 synchronized (DoubleCheckLocking.class){ //再次判断,若拿了锁很有可能出现还没来得及初始化就释放了锁 //导致可能创建多个实例对象 if(instance == null){ instance = new DoubleCheckLocking(); } } } return instance; } }

使用volatile关键字修饰instance变量

private static volatile DoubleCheckLocking instance=null;

1.4.1优点 使用双重检查锁进行多层判断,保证了对象实例化使用volatile关键字禁止了JVM的指令重排序 1.5静态内部类 package com.technologystatck.designpattern.modereview.singleton; public class StaticInner { //1.通过静态内部类实例化对象 private static class StaticInnerSingleton{ private static StaticInner instance = new StaticInner(); } //2.私有化构造方法 private StaticInner(){ } //3.创建静态方法返回实例化的对象 public static StaticInner getInstance(){ return StaticInnerSingleton.instance; } } 1.5.1优点 没有加锁,线程安全即时用再加载,并发性能高 1.6枚举类 package com.technologystatck.designpattern.modereview.singleton; enum Enums { //创建枚举类的实例 INSTANCE; //对单例对象的进行相关操作的方法 public void doSingleton(){ System.out.println("正在执行枚举类实现的单例对象的方法"); } } 1.6.1优点 不需要考虑序列化问题不需要考虑反射问题 1.7ThreadLocal package com.technologystatck.designpattern.modereview.singleton; public class ThreadLocals { //1.初始化ThreadLocal,同时实例化对象 private static ThreadLocal threadInstance = new ThreadLocal(); private static ThreadLocals instance=null; //2.使用静态方法将实例化的对象返回 public static ThreadLocals getInstance(){ if(threadInstance.get()==null){ createInstance(); } return instance; } //3.创建实例化对象的方法 private static final void createInstance(){ synchronized (ThreadLocals.class){ if(instance==null){ instance=new ThreadLocals(); } } //设置非空值,以便后续判断不再执行创建操作 threadInstance.set(threadInstance); } //4.调用remove方法清除当前线程的threadInstance变量的值 public static void remove(){ threadInstance.remove(); } } 1.7.1优点 保证了线程安全即时用再初始化 2.Proxy 代理模式 2.1静态代理 2.1.1静态代理的实现思路 静态代理需要先定义接口被代理对象与代理对象一起实现相同的接口通过调用相同的方法来调用目标对象的方法

小明想要购买一套房子,他决定寻求一家房屋中介来帮助他找到一个面积超过100平方米的房子,只有符合条件的房子才会被传递给小明查看。

package com.technologystatck.designpattern.modereview.proxy; public class StaticProxy { public static void main(String[] args) { House house1 = new House("武汉", 101); House house2 = new House("上海", 201); House house3 = new House("天津", 81); House house4 = new House("深圳", 88); HouseProxy houseProxy = new HouseProxy(); houseProxy.tradeHouse(house1); houseProxy.tradeHouse(house2); houseProxy.tradeHouse(house3); houseProxy.tradeHouse(house4); } } //1.定义抽象接口 //房屋交易接口 interface HouseTransaction{ //定义交易房子的方法 void tradeHouse(House house); } //2.定义被代理对象 class Seller implements HouseTransaction{ @Override public void tradeHouse(House house) { System.out.println("我是卖家,我在"+house.getAddress()+"卖"+house.getArea()+"平房子"); } } //3.定义代理对象 //相当于房屋中介 class HouseProxy implements HouseTransaction{ @Override public void tradeHouse(House house) { if(house.getArea()>100){ System.out.println("我是小明委托的中介,我在"+house.getAddress()+"看"+house.getArea()+"平房子"); } } } //定义房子类 class House{ private String address; private int area; public House() { } public House(String address, int area) { this.address = address; this.area = area; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public int getArea() { return area; } public void setArea(int area) { this.area = area; } @Override public String toString() { return "House{" + "address='" + address + '\'' + ", area=" + area + '}'; } } 2.1.2优点 静态代理在不改变目标对象的前提下,实现了对目标对象的功能扩展。 2.2动态代理 2.2.1动态代理的实现思路 需要代理类实现接口,使用Proxy.newProxyInstance方法生成代理类实现InvocationHandler中的invoke方法,实现增强功能
ClassLoader loader:指定当前目标对象使用类加载器,获取加载器的方法是固定的。Class<?>[] interfaces:目标对象实现的接口的类型,使用泛型方式确认类型。InvocationHandler h:事件处理,执行目标对象的方法时,会触发事件处理器的方法,会把当前执行目标对象的方法作为参数传入

小明想要购买一套房子,他决定寻求一家房屋中介来帮助他找到一个面积超过100平方米的房子,只有符合条件的房子才会被传递给小明查看。买房还需要一些手续,他需要房屋中介来帮助他履行完这些手续。

package com.technologystatck.designpattern.modereview.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.ArrayList; public class StaticProxy { public static void main(String[] args) { House house1 = new House("北京", 101); House house2 = new House("上海", 201); House house3 = new House("广州", 81); House house4 = new House("深圳", 88); ArrayList<House> houses = new ArrayList<>(); houses.add(house1); houses.add(house2); houses.add(house3); houses.add(house4); HouseProxy houseProxy=null; for (House house : houses) { HouseTransaction target = new Seller(); HouseTransaction proxy = (HouseTransaction) new HouseProxy(target).getProxy(); if(house.getArea()>100){ proxy.tradeHouse(house); proxy.serviceCharges(house); } } } } //1.定义抽象接口 //房屋交易接口 interface HouseTransaction{ //定义交易房子的方法 void tradeHouse(House house); void serviceCharges(House house); } //2.定义被代理对象 class Seller implements HouseTransaction{ @Override public void tradeHouse(House house) { System.out.println("有一个"+house.getAddress()+"的"+house.getArea()+"平房子"); } @Override public void serviceCharges(House house) { System.out.println("可以交接"+house.getAddress()+"的"+house.getArea()+"平房子手续"); } } //3.定义代理对象 //相当于房屋中介 class HouseProxy{ private Object target; public HouseProxy(Object o) { this.target = o; } public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { //使用Proxy.newProxyInstance方法生成代理对象, //实现InvocationHandler中的 invoke方法, //在invoke方法中通过反射调用代理类的方法,并提供增强方法 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("House Proxy动态代理"); Object invoke = method.invoke(target, args); return invoke; } }); } } //定义房子类 class House{ private String address; private int area; public House() { } public House(String address, int area) { this.address = address; this.area = area; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public int getArea() { return area; } public void setArea(int area) { this.area = area; } @Override public String toString() { return "House{" + "address='" + address + '\'' + ", area=" + area + '}'; } }

优点:不需要实现接口,但是目标对象需要实现接口

2.3Cglib代理 2.3.1Cglib代理的实现思路 通过enhancer来生成代理类,通过实现MethodInterceptor接口,并实现其中的intercept方法在该方法中可以添加增强方法,并利用反射Method或MethodProxy继承类来调用原方法 package com.technologystatck.designpattern.modereview.proxy; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; import java.util.ArrayList; public class CglibProxy { public static void main(String[] args) { House house1 = new House("北京", 101); House house2 = new House("上海", 201); House house3 = new House("广州", 81); House house4 = new House("深圳", 88); ArrayList<House> houses = new ArrayList<>(); houses.add(house1); houses.add(house2); houses.add(house3); houses.add(house4); for (House house : houses) { HouseTransaction proxyInstance = (HouseTransaction) new HouseProxy().getProxyInstance(Seller.class); if(house.getArea()>100){ proxyInstance.tradeHouse(house); proxyInstance.serviceCharges(house); } } } } //1.定义抽象接口 //房屋交易接口 interface HouseTransaction{ //定义交易房子的方法 void tradeHouse(House house); void serviceCharges(House house); } //2.定义被代理对象 class Seller implements HouseTransaction{ @Override public void tradeHouse(House house) { System.out.println("有一个"+house.getAddress()+"的"+house.getArea()+"平房子"); } @Override public void serviceCharges(House house) { System.out.println("可以交接"+house.getAddress()+"的"+house.getArea()+"平房子手续"); } } //3.定义代理对象 //相当于房屋中介 class HouseProxy implements MethodInterceptor { //给目标对象创建一个代理对象 public Object getProxyInstance(Class c){ //1.工具类 Enhancer enhancer = new Enhancer(); //2.设置父类 enhancer.setSuperclass(c); //3.设置回调函数 enhancer.setCallback(this); //4.创建子类(代理对象) return enhancer.create(); } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("Cglib代理处理"); Object object = methodProxy.invokeSuper(o, objects); return object; } } //定义房子类 class House{ private String address; private int area; public House() { } public House(String address, int area) { this.address = address; this.area = area; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public int getArea() { return area; } public void setArea(int area) { this.area = area; } @Override public String toString() { return "House{" + "address='" + address + '\'' + ", area=" + area + '}'; } }
Cglib的maven依赖 <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.3.0</version> </dependency> 2.3.2优点 无需代理类实现接口 3.Adapter适配器模式 3.1类的适配器模式的实现思路(继承实现) 定义期望获得的功能接口,完成扩展定义现有的接口,也就是需要被适配的接口定义现有接口的具体实现类,需要实现现有接口定义一个类适配器,通过继承现有接口来完成现有接口的扩展

小明购买了一台新电脑,该电脑使用 TypeC 接口,他已经有了一个USB接口的充电器和数据线,为了确保新电脑可以使用现有的USB接口充电器和数据线,他购买了一个TypeC到USB的扩展坞。使用适配器模式设计并实现这个扩展坞系统,确保小明的新电脑既可以通过扩展坞使用现有的USB接口充电线和数据线,也可以使用TypeC接口充电。

package com.technologystatck.designpattern.modereview.adapter; public class ClassAdapter { public static void main(String[] args) { //实例化适配器,相当于就可以通过适配器完成两种接口充电 AdapterCharge adapterCharge = new AdapterCharge(); adapterCharge.chargeUseUSB(); adapterCharge.chargeUseTypeC(); } } //定义一个期望获得的功能接口 interface TypeCTarget{ //使用TypeC接口充电 void chargeUseTypeC(); } //定义现有的USB接口 interface USBTarget{ //使用USB接口充电 void chargeUseUSB(); } //现有的接口具体实现类,USB class ConcreteUSBTarget implements USBTarget{ @Override public void chargeUseUSB() { System.out.println("正在通过USB接口充电"); } } //类适配器,相当于TypeC到USB充电的扩展坞 //继承现有接口来完成对现有接口的扩展 class AdapterCharge extends ConcreteUSBTarget implements TypeCTarget{ //完成USB接口充电 @Override public void chargeUseUSB() { super.chargeUseUSB(); } //完成TypeC接口充电 @Override public void chargeUseTypeC() { System.out.println("可以使用TypeC接口充电"); } } 3.2对象的适配器模式(扩展实现)

定义期望获得的功能接口,完成扩展

定义现有的接口,也就是需要被适配的接口

定义现有接口的具体实现类,需要实现现有接口

定义一个类适配器,通过继承现有接口,

持有现有接口类一个实例,并完成其扩展功能,以此来实现目标接口

package com.technologystatck.designpattern.modereview.adapter; public class ObjectAdapter { public static void main(String[] args) { USBTarget concreteUSBTarget = new ConcreteUSBTarget(); AdapterCharge adapterCharge = new AdapterCharge(concreteUSBTarget); adapterCharge.chargeUseTypeC(); } } //定义一个期望获得的功能接口--使用TypeC接口充电 interface TypeCTarget{ //使用TypeC接口充电 void chargeUseTypeC(); } //定义现有的USB接口 interface USBTarget{ //使用USB接口充电 void chargeUseUSB(); } //现有的接口具体实现类,USB class ConcreteUSBTarget implements USBTarget{ @Override public void chargeUseUSB() { System.out.println("正在通过USB接口充电"); } } //类适配器,相当于TypeC到USB充电的扩展坞 //继承现有接口来完成对现有接口的扩展,持有实例完成扩展功能 class AdapterCharge implements TypeCTarget{ private USBTarget usbTarget; public AdapterCharge() { } public AdapterCharge(USBTarget usbTarget) { this.usbTarget = usbTarget; } //在现有功能的基础上扩展功能 @Override public void chargeUseTypeC() { usbTarget.chargeUseUSB(); System.out.println("可以使用TypeC接口充电"); } } 3.3优点 可以让任何两个没有关联的类一起运行提高了类的复用,将现有接口实现类进行隐藏 4.Chain责任链模式 4.1责任链的实现思路 定义请求对象,含有很多属性,表示一个请求定义抽象处理者,主要用于处理请求,同时设置方法参数来保存其他的处理者定义具体处理者,实现抽象处理者接口,处理自己负责的请求,并且实例化抽象处理者,可以访问到下一个处理者,若能处理请求则在此处处理,若不能处理请求且处理者参数不为空则将请求发送给下一个处理者

小明所在的公司请假需要在OA系统上发布申请,整个请求流程包括多个处理者,每个处理者负责处理不同范围的请假天数,如果一个处理者不能处理请求,就会将请求传递给下一个处理者,请你实现责任链模式,可以根据请求天数找到对应的处理者。

审批责任链由主管(Supervisor), 经理(Manager)和董事(Director)组成,他们分别能够处理3天、7天和10天的请假天数。如果超过10天,则进行否决。

package com.technologystatck.designpattern.modereview.chainofresponsibility; public class Chain { public static void main(String[] args) { Request requestObject1 = new Request("张三","病假",3); Request requestObject2 = new Request("李四","公假",6); Request requestObject3 = new Request("王五","事假",9); Request requestObject4 = new Request("赵六","事假",12); //定义责任链对象 Supervisor supervisor = new Supervisor(); Manager manager = new Manager(supervisor); Director director = new Director(manager); //执行 supervisor.handlerRequest(requestObject1); manager.handlerRequest(requestObject2); director.handlerRequest(requestObject3); director.handlerRequest(requestObject4); } } //定义请求对象 class Request{ //请求人 String name; //请求事件 String requestStr; //请求天数 int day; public Request(String name, String requestStr, int day) { this.name = name; this.requestStr = requestStr; this.day = day; } public String getName() { return name; } public String getRequestStr() { return requestStr; } public int getDay() { return day; } } //定义抽象处理者 interface CurrentHandler{ //设置处理当前请求的方法 void handlerRequest(Request request); } //定义具体处理者-主管 class Supervisor implements CurrentHandler{ //设置条件天数 private static final int APPROVE_DAY=3; //设置下一个处理者 private CurrentHandler nextHandler; public Supervisor() { } public Supervisor(CurrentHandler nextHandler) { this.nextHandler = nextHandler; } @Override public void handlerRequest(Request request) { if(request.getDay()<=APPROVE_DAY){ System.out.println(request.getName()+" Approved by Supervisor."); }else if(nextHandler !=null){ nextHandler.handlerRequest(request); }else{ System.out.println(request.getName()+" No Approve by Supervisor."); } } } //定义具体处理者-主管 class Manager implements CurrentHandler{ //设置条件天数 private static final int APPROVE_DAY=7; //设置下一个处理者 private CurrentHandler nextHandler; public Manager(CurrentHandler nextHandler) { this.nextHandler = nextHandler; } @Override public void handlerRequest(Request request) { if(request.getDay()<=APPROVE_DAY){ System.out.println(request.getName()+" Approved by Manager."); }else if(nextHandler !=null){ nextHandler.handlerRequest(request); }else{ System.out.println(request.getName()+" No Approve by Manager."); } } } //定义具体处理者-董事 class Director implements CurrentHandler{ //设置条件天数 private static final int APPROVE_DAY=10; //设置下一个处理者 private CurrentHandler nextHandler; public Director(CurrentHandler nextHandler) { this.nextHandler = nextHandler; } @Override public void handlerRequest(Request request) { if(request.getDay()<=APPROVE_DAY){ System.out.println(request.getName()+" Approved by Director."); }else if(nextHandler !=null){ nextHandler.handlerRequest(request); }else{ System.out.println(request.getName()+" No Approve by Director."); } } } 4.2优点 将多个处理器组合在一起,依次处理请求添加新的处理器或者重新排列处理器非常容易 5.Simple Factory简单工厂模式 5.1简单工厂的实现思路 定义简单工厂类,用于实现所有实例对象的内部逻辑,其中创建产品的方法可以被外界调用,创建所需的产品对象定义抽象产品类,是工厂类创建的所有对象的父类,封装了各种产品对象的公有放啊,定义具体产品类,每一个具体产品类都继承自抽象产品类,需要实现抽象产品类的方法

小明家有两个工厂,一个用于生产圆形积木,一个用于生产方形积木,请你帮他设计一个积木工厂系统,记录积木生产的信息。

package com.technologystatck.designpattern.modereview.simplefactory; import java.util.ArrayList; import java.util.List; public class SimpleFactory { public static void main(String[] args) { BlockFactorySystem blockFactorySystem = new BlockFactorySystem(); blockFactorySystem.BuildBlocks("redirect",2); blockFactorySystem.BuildBlocks("square",2); //创建圆形 BlockFactory.factoryCreateBlock("redirect").createBlock(); //创建方形 BlockFactory.factoryCreateBlock("square").createBlock(); } } //定义抽象产品类 abstract class Product{ //创建积木方法 abstract void createBlock(); } //定义具体产品类--圆形积木 class RedirectBlock extends Product{ @Override void createBlock() { System.out.println("创建圆形积木"); } } //定义具体产品类--方形积木 class SquareBlock extends Product{ @Override void createBlock() { System.out.println("创建方形积木"); } } //定义工厂类 class BlockFactory{ public static Product factoryCreateBlock(String type){ if(type.equals("redirect")){ return new RedirectBlock(); }else if(type.equals("square")){ return new SquareBlock(); }else{ throw new IllegalArgumentException("无效的积木"); } } } //积木工厂系统 class BlockFactorySystem{ //定义集合存放积木信息 private List<Product> products=new ArrayList(); //创建积木方法 public void BuildBlocks(String type,int nums){ for(int i=0;i<nums;i++){ if(type.equals("redirect") || type.equals("square")) BlockFactory.factoryCreateBlock(type).createBlock(); } } } 6.Factory Method工厂方法模式 6.1工厂方法的实现思路 定义抽象工厂接口,用于创建一族产品的方法,每个方法对应一种产品定义具体工厂类,实现抽象工厂接口,用于创建一组具体产品的对象定义抽象产品接口,为每种产品声明接口,在抽象产品接口中声明产品所有的业务方法定义具体产品类,定义了具体工厂生产的具体产品对象,实现抽象产品接口中声明的业务方法

小明家有两个工厂,一个用于生产圆形积木,一个用于生产方形积木,请你帮他设计一个积木工厂系统,记录积木生产的信息。

package com.technologystatck.designpattern.modereview.factorymethod; import java.util.ArrayList; import java.util.List; public class FactoryMethod { public static void main(String[] args) { new BlockFactorySystem().BuildBlocks(new RedirectBlockFactory(),3); new BlockFactorySystem().BuildBlocks(new SquareBlockFactory(),2); System.out.println("====================="); RedirectBlockFactory redirectBlockFactory = new RedirectBlockFactory(); redirectBlockFactory.createBlock().createBlockProduct(); BlockProduct block = new SquareBlockFactory().createBlock(); block.createBlockProduct(); } } //定义抽象产品接口 interface BlockProduct{ void createBlockProduct(); } //定义具体产品实现类-圆形积木 class RedirectBlock implements BlockProduct{ @Override public void createBlockProduct() { System.out.println("创建圆形积木"); } } //定义具体产品实现类-方形积木 class SquareBlock implements BlockProduct{ @Override public void createBlockProduct() { System.out.println("创建方形积木"); } } //定义抽象工厂接口 interface BlockFactory{ //创建积木 BlockProduct createBlock(); } //定义具体工厂实现类-圆形积木 class RedirectBlockFactory implements BlockFactory{ @Override public BlockProduct createBlock() { return new RedirectBlock(); } } //定义具体工厂实现类-方形积木 class SquareBlockFactory implements BlockFactory{ @Override public BlockProduct createBlock() { return new SquareBlock(); } } //定义工厂系统 class BlockFactorySystem{ private List<BlockProduct> blockProducts=new ArrayList<BlockProduct>(); public void BuildBlocks(BlockFactory factory,int nums){ for(int i=0;i<nums;i++){ BlockProduct block = factory.createBlock(); blockProducts.add(block); block.createBlockProduct(); } } } 6.2优点 工厂方法只有一个抽象产品类和一个抽象工厂类,但可以派生出多个具体产品类和具体工厂类每个具体工厂类只能创建一个具体产品类的实例 7.Template Method模板方法模式 7.1模板方法的实现思路

定义一个抽象模板类,负责给出算法的轮廓和骨架,由一个模板方法和若干个基本方法构成

定义模板方法:定义了算法的骨架,按某种顺序调用其包含的基本方法

定义基本方法,是实现算法各个步骤的方法,是模板方法的组成部分

抽象方法:由抽象类声明、由其具体子类实现

具体方法:由一个抽象类或具体类声明并实现,其子类可以进行覆盖也可以直接继承

钩子方法:在抽象类中已经实现,包括用于判断的逻辑方法和需要子类重写的空方法两种

用于判断的逻辑方法,方法名一般为isXxx,返回值类型为boolean类型

可以定义多个具体模板类,实现抽象模板类中所定义的抽象方法和钩子方法,是顶级逻辑的组成步骤


小明喜欢品尝不同类型的咖啡,她发现每种咖啡的制作过程有一些相同的步骤,他决定设计一个简单的咖啡制作系统,使用模板方法模式定义咖啡的制作过程。系统支持两种咖啡类型:美式咖啡(American Coffee)和拿铁(Latte)。

咖啡制作过程包括以下步骤:

研磨咖啡豆 Grinding coffee beans冲泡咖啡 Brewing coffee添加调料 Adding condiments

其中,美式咖啡和拿铁的调料添加方式略有不同, 拿铁在添加调料时需要添加牛奶Adding milk

package com.technologystatck.designpattern.modereview.template; public class Template { public static void main(String[] args) { CoffeeTemplate american = new American(); CoffeeTemplate latte = new Latte(); CoffeeTemplate milk = new Milk(); //通过钩子方法进行判断 if (!american.isMilk()) { american.makeCoffee(); } if (!latte.isMilk()) { latte.makeCoffee(); } if (!milk.isMilk()) milk.makeMilk(); } } abstract class CoffeeTemplate { //咖啡名称 private String coffeeName; //构造函数 public CoffeeTemplate(String coffeeName) { this.coffeeName = coffeeName; } //定义制造咖啡的模板方法 final void makeCoffee() { System.out.println("making " + coffeeName + ": "); grindingCoffeeBeans(); brewingCoffee(); addingCondiments(); } //定义制造牛奶的模板方法 final void makeMilk() { System.out.println("making " + coffeeName + ": "); addingCondiments(); } //定义实现模板方法的基本方法 //研磨方法 void grindingCoffeeBeans() { System.out.println("研磨咖啡豆"); } //冲泡咖啡 void brewingCoffee() { System.out.println("冲泡咖啡"); } //添加调料根据咖啡的种类,调料不一样 //定义基本方法中的抽象方法 abstract void addingCondiments(); //定义钩子方法,判断是否是牛奶,牛奶不需要添加其他 boolean isMilk() { return false; } } //定义美式咖啡具体实现类 class American extends CoffeeTemplate { public American() { super("American Coffee"); } @Override void addingCondiments() { System.out.println("添加American Coffee的调料"); } } //定义拿铁咖啡具体实现类 class Latte extends CoffeeTemplate { public Latte() { super("Latte Coffee"); } @Override void addingCondiments() { System.out.println("添加Latte Coffee的调料"); } } //定义牛奶具体实现类,但是需要判断是否是牛奶 class Milk extends CoffeeTemplate { public Milk() { super("Milk"); } @Override void addingCondiments() { System.out.println("牛奶不需要添加调料"); } @Override boolean isMilk() { System.out.println("是牛奶,不需要添加调料"); return true; } } 7.2优点 当多个子类存在公共的行为时,可以将其提取出来并集中到一个公共父类中以避免代码重复。当需要控制子类的扩展时,模板方法只在特定点调用钩子操作 8.Decorator 装饰器模式 8.1装饰器的实现思路 定义抽象构件,通过抽象接口规范准备接收附加责任的对象定义具体构件,实现抽象构件,为装饰器添加一些职责定义抽象装饰,继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能定义具体装饰,实现抽象装饰的相关方法,并给出具体构件对象添加附加的功能

小明喜欢品尝不同口味的咖啡,他发现每种咖啡都可以加入不同的调料,比如牛奶、糖和巧克力。他决定使用装饰者模式制作自己喜欢的咖啡。

请设计一个简单的咖啡制作系统,使用装饰者模式为咖啡添加不同的调料。系统支持两种咖啡类型:黑咖啡(Black Coffee)和拿铁(Latte)。

package com.technologystatck.designpattern.modereview.decorator; public class Decorator { public static void main(String[] args) { CoffeeComponent latteCoffee = new LatteCoffee(); CoffeeComponent blackCoffee = new BlackCoffee(); latteCoffee.makeCoffee(); blackCoffee.makeCoffee(); System.out.println("===================="); new Milk(latteCoffee).makeCoffee(); new Sugar(blackCoffee).makeCoffee(); } } //定义抽象构件 abstract class CoffeeComponent{ //需要添加的调料名字 private String seasoning; public CoffeeComponent() { } //可以自己手动传参 public CoffeeComponent(String seasoning) { this.seasoning = seasoning; } public String getSeasoning() { return seasoning; } public void setSeasoning(String seasoning) { this.seasoning = seasoning; } //制作咖啡的方法 abstract void makeCoffee(); } //定义具体构件 //黑咖啡的制作 class BlackCoffee extends CoffeeComponent{ public BlackCoffee() { super("黑咖啡浓缩原液"); } @Override void makeCoffee() { System.out.println("making "+super.getSeasoning()+" black coffee"); } } //拿铁的制作 class LatteCoffee extends CoffeeComponent{ public LatteCoffee() { super("拿铁咖啡浓缩原液"); } @Override void makeCoffee() { System.out.println("making "+super.getSeasoning()+" latte coffee"); } } //定义抽象装饰 abstract class CoffeeDecorator extends CoffeeComponent{ //实例化抽象构件 private CoffeeComponent coffeeComponent; public CoffeeComponent getCoffeeComponent() { return coffeeComponent; } public void setCoffeeComponent(CoffeeComponent coffeeComponent) { this.coffeeComponent = coffeeComponent; } //默认构造方法 public CoffeeDecorator(String seasoning, CoffeeComponent coffeeComponent) { super(seasoning); this.coffeeComponent = coffeeComponent; } } //定义具体装饰 //黑咖啡具体装饰类 class Milk extends CoffeeDecorator{ public Milk(CoffeeComponent coffeeComponent) { //添加额外的操作 //添加半杯奶 super("半杯奶", coffeeComponent); } @Override void makeCoffee() { System.out.println("制作"+super.getSeasoning()+"的黑咖啡"); } } class Sugar extends CoffeeDecorator{ //添加额外的操作 //添加两勺糖 public Sugar( CoffeeComponent coffeeComponent) { super("两勺糖", coffeeComponent); } @Override void makeCoffee() { System.out.println("添加了"+super.getSeasoning()+"的拿铁"); } } 8.2优点 在不影响其他对象的情况下,动态的给单个对象添加职责。声明目标对象时需要实现与目标类相同的业务接口可以在不修改目标类的前提下增强目标方法 9.Observer 观察者模式 9.1观察者的实现思路 定义抽象主题,定义的接口中提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者对象的抽象方法定义具体主题,用于实现抽象主题中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象定义抽象观察者,定义的接口中包含了更新自己的抽象方法,当接到具体主题的更改通知时被调用定义具体观察者,实现抽象观察者中定义的抽象方法,当主题内部状态发生变化时,就通知到具体观察者并进行处理

小明所在的学校有一个时钟(主题),每到整点时,它就会通知所有的学生(观察者)当前的时间,请你使用观察者模式实现这个时钟通知系统。

注意点:时间从 0 开始,并每隔一个小时更新一次。

package com.technologystatck.designpattern.modereview.observer; import java.util.ArrayList; import java.util.List; public class ClockObserver { public static void main(String[] args) { Clock clock = new Clock(); ConcreteObserver concreteObserver1 = new ConcreteObserver("张三"); ConcreteObserver concreteObserver2 = new ConcreteObserver("李四"); ConcreteObserver concreteObserver3 = new ConcreteObserver("王五"); //注册三个新用户 clock.register(concreteObserver1); clock.register(concreteObserver2); clock.register(concreteObserver3); //通知方法通知所有的人 clock.notifys("正在注册新用户"); //提供注销用户 clock.removes(concreteObserver2); //通知方法通知所有的人 clock.notifys("正在注销用户"+concreteObserver2.getName()); for(int i=0,updates=3;i<updates;i++){ clock.tick(); } } } //定义抽象主题 interface Subject{ //增加订阅者 void register(Observer observer); //删除订阅者 void removes(Observer observer); //通知订阅者 void notifys(String messages); } //定义具体主题 class Clock implements Subject{ //存储所有的用户 private List<Observer> observers=new ArrayList<>(); private int hour=0; @Override public void register(Observer observer) { observers.add(observer); } @Override public void removes(Observer observer) { observers.remove(observer); } @Override public void notifys(String messages) { for (Observer observer : observers) { //调用更新方法通知全局 observer.update(messages); } } //定义方法 模拟时钟 public void tick(){ hour=(hour+1)%24; //通知时间 notifys("现在时间: "+hour); } } //定义抽象观察者 interface Observer{ void update(String messages); } //定义具体观察者 class ConcreteObserver implements Observer{ private String name; public ConcreteObserver(String name) { this.name = name; } public String getName() { return name; } @Override public void update(String messages) { System.out.println(this.name+" --> "+messages); } } 9.2优点 对象间存在一对多关系,一个对象的状态发生改变会影响其他对象类似广播机制,不需要具体收听者,只需分发广播 10.Strategy 策略模式 10.1策略模式的实现思路 抽象策略类,定义一个公共接口,各种不同的算法以不同的方式实现接口,环境角色使用该接口调用不同的算法具体策略类,实现抽象策略定义的接口,并提供具体的算法实现环境类(上下文类),包含一个策略实例,并在需要时调用策略对象的方法

小明家的超市推出了不同的购物优惠策略,你可以根据自己的需求选择不同的优惠方式。其中,有两种主要的优惠策略:

九折优惠策略:原价的90%。满减优惠策略:购物满一定金额时,可以享受相应的减免优惠。

具体的满减规则如下:

满100元减5元

满150元减15元

满200元减25元

满300元减40元

请你设计一个购物优惠系统,用户输入商品的原价和选择的优惠策略编号,系统输出计算后的价格。

package com.technologystatck.designpattern.modereview.strategy; public class Strategy { public static void main(String[] args) { DiscountContext discountContext = new DiscountContext(); DiscountStrategy9 discountStrategy9 = new DiscountStrategy9(); DiscountStrategyFull discountStrategyFull = new DiscountStrategyFull(); // discountContext.setStrategy(discountStrategy9); discountContext.setStrategy(discountStrategyFull); int price = discountContext.applyDiscount(120); System.out.println("折扣后的价格"+price); } } //定义抽象策略类 interface DiscountStrategy { //定义算法方法 int applyDiscount(int originalPrice); } //定义具体策略类 //定义九折优惠策略类 class DiscountStrategy9 implements DiscountStrategy { @Override public int applyDiscount(int originalPrice) { return (int) (originalPrice * 0.9); //返回九折优惠后的价格(保留两位小数) } } //定义满减优惠策略类 class DiscountStrategyFull implements DiscountStrategy { //定义满足的价格 private int[] thresholds={100,150,200,300}; //定义满减的价格 private int[] discounts={5,15,25,40}; @Override public int applyDiscount(int originalPrice) { //先遍历满足的价格 for(int i=thresholds.length-1;i>=0;i--){ //若价格有大于或等于满足价格中 //从最高的价格开始遍历,若有,则返回满减价格 //例如,如果大于300,则因为从后开始遍历,所以满减的价格也是从后开始遍历,则是减去40 if(originalPrice>=thresholds[i]){ //返回满减价格 return originalPrice-discounts[i]; } } //若价格小于满足价格数组,则返回原价 return originalPrice; } } //定义上下文类 class DiscountContext { private DiscountStrategy strategy; //设置方法 public void setStrategy(DiscountStrategy strategy) { this.strategy = strategy; } //输入原价格 //通过该类来调用折扣方法,进行价格折扣 public int applyDiscount(int orignalPrice) { return strategy.applyDiscount(orignalPrice); } } 10.2优点 一个系统需要动态地在几种算法中选择一种时,可将每个算法封装到策略类中系统中各个算法独立,根据运行时动态选择具体要执行的行为
标签:

十大设计模式总结版由讯客互联手机栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“十大设计模式总结版