针对接口编程,真正的意思是“针对超类编程”(接口通常是一个抽象类或者是一个接口)。
例子:
针对现实编程:
Dog dog=new Dog();
dog.bark();
针对接口/超类编程
Animal animal=new Dog();
animal.bark();
更棒的是,子类实例化的动作不再需要在代码中硬编码。
Animal animal=getAnimal();
animal.bark();
在编译期间,我们无法知道实际的子类型是什么,我们只关心它是如何bark的就行了。
在运行时,我们可以set子类型,从而动态的执行具体的子类方法。
这种编程思想很多,比方说:日志,我们只针对接口编程,具体子类型,在运行时才知道。
private static final Logger log = LoggerFactory.getLogger(ArticleManagerImpl.class);
log.error("EZ编程网-面向接口编程");
具体log的实现,要在运行期间才知道。
策略模式的例子:
人:男人、女人、木头人、机器人。
人会站立、走路、说话。
男人会站立、走路、说话。
女人会站立、走路、说话。
木头人会站立、不会走路、不会说话。
机器人会站立、会走路、不会说话。
单纯的继承,已经不能满足需求,我们需要把会变的提取出来,不变的继承下去。
如:所有人都会站立,所以站立可以采用继承。
但是说话和走路并不是所有人都会,所以要把这些会变的,放到运行时,动态的解决。
这里走路和说话就是人的策略,
不同的人可以使用不同的策略,如稻草人使用不会说话的策略。
第一种实现方式,编译时解决,写走路和说话两个接口,让男人女人再实现这两个接口,机器人再实现走路接口。
这种方式,增加代码量,而且不容易维护。
第二种实现方式,运行时解决,采用策略模式实现:运行时,想改变人的行为,只需要调用人的setter方法就可以了。
大家要深入理解下面这段话:
把站立和说话这些不确定的方法做成接口组合进来,使用接口编程完成站立和说话的方法内容。分别实现接口,在运行时,动态的把接口的实现setter进来就可以了,这样子类继承到的站立和说话方法就会随着动态setter的变化而变化。
我们把人走路和说话行为想成“一族算法”。
策略模式定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。这就是策略模式。
package com.ez.impl; import com.ez.Human; /** 人:男人、女人、稻草人、机器人 所有人会站立。 男人会站立、走路、说话。 女人会站立、走路、说话。 稻草人会站立、不会走路、不会说话。 机器人会站立、会走路、不会说话。 每个人都有自己的外观。 * @author 窗外赏雪 * */ public class Test { public static void main(String[] args) { System.out.println("============稻草人============="); Human scarecrow=new Scarecrow(); scarecrow.speak(); scarecrow.walk(); scarecrow.display(); scarecrow.stand(); System.out.println("============机器人============="); Human android=new Android(); android.speak(); android.walk(); android.display(); android.stand(); System.out.println("============男人============="); Human man=new Man(); man.speak(); man.walk(); man.display(); man.stand(); System.out.println("============女人============="); Human women=new Women(); women.speak(); women.walk(); women.display(); women.stand(); } }
package com.ez; /** * 人:会站立、走路、说话。 * @author 窗外赏雪(EZ编程网) * */ public abstract class Human { /** * 每个人都有说话和走路的行为,人是通过组合得到这两个行为的。 * 我们应该多用组合少用继承。 */ protected SpeakBehavior speakBehavior; protected WalkBehavior walkBehavior; /** * 不同类别的人,说话方式不同,如稻草人跟机器人都不会说话。 * 把编译期间不确定的,用接口编程。 */ public void speak(){ speakBehavior.speak(); } /** * 不同类别的人,走路方式不同,如稻草人不会走路。 * 把编译期间不确定的,用接口编程。 */ public void walk(){ walkBehavior.walk(); } /** * 每种类别的人,表现出来都不一样,所以用抽象方法。 */ public abstract void display(); /** * 所有人都会站立,所以在超类中实现,这样所有的子类,都会站立。 */ public void stand(){ System.out.println("只要是人,都会站立"); } }
package com.ez.impl; import com.ez.Human; public class Android extends Human{ /** * 在运行时,动态创建子类。 * 机器人不会说话、会走路 */ public Android() { speakBehavior=new SpeakNoWay(); walkBehavior=new WalkWithLeg(); } @Override public void display() { System.out.println("android dispaly"); } }
package com.ez.impl; import com.ez.Human; public class Women extends Human{ /** * 在运行时,动态创建子类。 * 女人会说话、会走路 */ public Women() { speakBehavior= new SpeakWithMouth(); walkBehavior = new WalkWithLeg(); } @Override public void display() { System.out.println("women display"); } }
package com.ez.impl; import com.ez.Human; public class Man extends Human{ /** * 在运行时,动态创建子类。 * 男人会说话、会走路 */ public Man() { speakBehavior=new SpeakWithMouth(); walkBehavior=new WalkWithLeg(); } @Override public void display() { System.out.println("man display"); } }
package com.ez.impl; import com.ez.Human; /** * 稻草人也是人 * @author 窗外赏雪 * */ public class Scarecrow extends Human{ /** * 在运行时,动态创建子类。 * 稻草人人不会说话、不会走路 */ public Scarecrow() { speakBehavior=new SpeakNoWay(); walkBehavior=new WalkNoWay(); } @Override public void display() { System.out.println("scarecrow display"); } }
package com.ez; public interface SpeakBehavior { /** * 说话 */ void speak(); }
package com.ez.impl; import com.ez.SpeakBehavior; /** * 这是说话行为的实现,给不会说话的人使用。 * @author 窗外赏雪 * */ public class SpeakNoWay implements SpeakBehavior{ @Override public void speak() { System.out.println("sorry I can't speak"); } }
package com.ez.impl; import com.ez.SpeakBehavior; /** * 这是说话行为的实现,给会说话的人使用。 * @author 窗外赏雪 * */ public class SpeakWithMouth implements SpeakBehavior{ @Override public void speak() { System.out.println("I can speak"); } }
package com.ez; public interface WalkBehavior { /** * 走路 */ void walk(); }
package com.ez.impl; import com.ez.WalkBehavior; /** * 这是走路行为的实现,给不会走路的人使用。 * @author 窗外赏雪 * */ public class WalkNoWay implements WalkBehavior{ @Override public void walk() { System.out.println("I can't walk"); } }
package com.ez.impl; import com.ez.WalkBehavior; /** * 这是走路行为的实现,给会走路的人使用。 * @author 窗外赏雪 * */ public class WalkWithLeg implements WalkBehavior{ @Override public void walk() { System.out.println("I can walk"); } }
相关推荐
策略模式结合模板方法模式
策略模式的 C++ 代码实现, ide :XCode
策略模式定义了方法族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。 还可以那家咖啡屋,记忆里很温馨,很sugar,或许很多温馨美好的回忆都是于咖啡有关的。 我们常常说设计...
所有模式都可分为类模式和对象模式两种,类模式是继承,对象模式是委托,而桥接模式和策略模式都是将任务委托给另外一个接口去实现,那么两者的区别什么呢?
主要介绍了详解SpringBoot结合策略模式实战套路,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
技术: 1. spring事件驱动(ApplicationEventPublisher) 2. 策略模式处理事件 目的: 1. 通过event,代码逻辑异步处理 2. 通过策略模式,构建具体监听实现 3. 解耦 4. 容错(降低代码块错误风险)
这是策略模式中的一个经典实例,通过鸭子问题,能让学习者更好的了解设计模式,这也是headfirst 设计模式中用的经典实例
深入浅出设计模式之抽象工厂模式+工厂方法模式+策略模式实现手机加工厂(加类图)
策略模式实例策略模式实例策略模式实例策略模式实例策略模式实例
策略模式代码,两种方式实现,第一种,通过map存储方式,第二种,通过配置文件加反射方式
策略模式的简单例子,根据《Head First设计模式》中第一章中的Duck编写
策略模式例子,纯代码,copy后即可运行; 1、如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。 2、一个系统需要动态地在几种算法中...
策略模式在实际项目中的应用二,该测试demo为普通项目,导入build path一下lib目录下的jar包,然后运行测试类即可在控制台看到测试结果
处理层的设计采用了设计模式中的策略模式、模板方法模式和工厂模式。 Server端和Client端的实现也采用了分层的设计方式,包含自定义的模型层、视图层和控制层。 说明:程序采用配置文件的方式进行初始化,运行时时请...
55-Java设计模式之策略模式与状态模式1
设计模式中的策略模式,同时兼容简单工厂模式,商场收银模式,易懂可用。
策略模式策略模式策略模式
javascript的策略模式和代理模式简介,附代码
在网络上看到几个加密解密算法,本着"取之于民用之于民"的方针测试一下,并用策略模式将这些算法封装共享。
设计模式中的策略模式,template模式详细讲解。