一、基于抽象类的模板设计模式:
换句话说,在软件开发中实现一个算法时,整体步骤很固定、通用,这些步骤已经在父类中写好了。但是某些部分易变,易变部分可以抽象出来,供不同子类实现。这就是一种模板模式。
:
/**
* 基类声明为抽象类的原因是
* 其子类必须实现其操作
*/
abstract class AbstractClass {
/**
* 模板方法,被声明为final以免子类改变这个算法的顺序
*/
final void templateMethod() {
}
/**
* 具体操作延迟到子类中实现
*/
abstract void primitiveOperation1();
abstract void primitiveOperation2();
/**
* 具体操作且共用的方法定义在超类中,可以被模板方法或子类直接使用
*/
final void concreteOperation() {
// 实现
}
/**
* 钩子方法是一类"默认不做事的方法"
* 子类可以视情况决定要不要覆盖它们。
*/
void hook() {
// 钩子方法
}
}
扩展上述类,引入”钩子“方法;超类实现:
abstract class CaffeineBeverage {
final void prepareRecipe() {
boilWater();
brew();
pourInCup();
// 如果顾客想要饮料我们才调用加料方法
if (customerWantsCondiments()){
addCondiments();
}
}
abstract void brew();
abstract void addCondiments();
void boilWater() {
System.out.println("Boiling water");
}
void pourInCup() {
System.out.println("Pouring into cup");
}
/**
* 钩子方法
* 超类中通常是默认实现
* 子类可以选择性的覆写此方法
* @return
*/
boolean customerWantsCondiments() {
return true;
}
}
:
class Tea extends CaffeineBeverage {
void brew() {
System.out.println("Steeping the tea");
}
void addCondiments() {
System.out.println("Adding Lemon");
}
}
class Coffee extends CaffeineBeverage {
void brew() {
System.out.println("Dripping Coffee through filter");}
void addCondiments() {
System.out.println("Adding Sugar and Milk");
}
/**
* 子类覆写了钩子函数,实现自定义功能
* @return
*/
public boolean customerWantsCondiments() {
String answer = getUserInput();
if (answer.equals("y")) {
return true;
}else {
return false;
}
}
private String getUserInput() {
String answer = null;
System.out.println("您想要在咖啡中加入牛奶或糖吗 (y/n)?");
Scanner scanner = new Scanner(System.in);
answer = scanner.nextLine();
return answer;
}
}
现实生活中的例子:用代码描述喝咖啡
a.把水烧开 b.将咖啡导入顾客杯子中 c.将咖啡倒入顾客杯子中 d.加糖和牛奶
public class Coffee{
//一键启动按钮,点这个按钮就能出一杯咖啡
public void prepareRecipe(){
boilWater();
brewCoffeeBag();
pourInCup();
addSugarAndMilk();
}
}
现在不想喝咖啡,想点一杯茶
class Tea{
public void prepareRecipe(){
boilWater();
steepTeaBag();
pourInCup();
addLemon();
}
}
出现的问题:1. 代码出现大量重复(烧水,倒入杯子这两个方法对于所有热饮,大家都是通用的)
2.假设每当扩展一种新的热饮,上述代码全得重写一遍。不方便扩展。
解决问题:将热饮设计为一个父类CaffineBeverage
Coffee extends CaffeineBeverage
Tea extends CaffeineBeverage
烧水和倒入杯子操作子类就可直接使用。对于制作饮品的具体流程,对于顾客来说是不可见的
abstract class CaffeineBeverage{
//制作流程是标准化的,封装到父类中
//子类只有使用权不能修改
public final void prepareRecipe(){
boilWater();
brew();
pourInCup();
addCondiments();
}
//对于浸泡和加调味品来说,不同子类实现细节不同,延迟到子类中去具体实现
public abstract void brew();
public abstract void addCondiments();
public void pourInCup(){
}
}
class Coffee extends CaffeineBeverage{
@Override
public void brew() {
System.out.println("brew coffee bag");
}
@Override
public void addCondiments() {
System.out.println("add sugar and milk");
}
}
class Tea extends CaffeineBeverage{
@Override
public void brew() {
System.out.println("steep tea bag");
}
@Override
public void addCondiments() {
System.out.println("add lemon");
}
}
代码中的细节解释:要保证所有加盟店的饮品在不同门店的味道都是相同的,就需要把制作流程prepareRecipe()封装到父类中,子类只能使用不能修改!
final修饰的方法子类只能使用,不能修改。
对于咖啡和茶来说,泡茶泡咖啡,加奶加柠檬就得具体子类去实现。–父类中无法实现,延迟到具体子类中实现–抽象方法
子类只需要关心子类独有的方法实现即可。共同的方法拿来即用
父类封装了核心方法(算法),子类只能使用不能修改,对于核心方法来说就是一种保护
要扩展一个新的子类,非常容易。
public boolean isCustomerWantsCondiments(){
return true;
}
钩子方法(hook)–加糖和牛奶,有的顾客就不要。–子类来决定
对于父类来说,制作饮品的最后一步默认都是加调味品
如果有的子类可以选择不加,覆写此方法即可。
二、代理设计模式:(代购)
代理设计模式是基于接口的
代理设计就是为其他对象提供一种代理以控制对这个对象的访问。
一个接口两个实现类,一个是真实业务类,另一个是辅助真实业务的代理类
最终将真实业务传递给代理类来完成整个业务的实现
举例:
顾客:真正付钱的人(提出问题)
代购:帮助买东西(辅助解决真实问题)
class ProxySubject implements ISubject{
private ISubject realSubject;
public ProxySubject(ISubject subject){
this.realSubject = subject;
}
public void preHandle(){
System.out.println("买飞机票去看漂亮妹妹~");
}
@Override
public void buyComputer() {
preHandle();
//付钱这个操作是由真实业务来处理的
this.realSubject.buyComputer();
postHandle();
}
public void postHandle() {
System.out.println("再回国");
}
}
代理模式的本质:所有的真实业务操作都会有一个与之辅助的工具类(功能类)共同完成。
代理模式在JavaEE中有着广泛的应用。EJB、WebService、Spring等技术都是代理模式的应用。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/110918.html