23种软件设计模式
介绍
将一个类的接口转换成客户希望的另外一个接口,适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作,属于结构型设计模式。
使用场景
已经存在的类,它的方法和需求不匹配(方法结果相同或相似)的情况。
适配器模式不是软件设计阶段考虑的设计模式,是随着软件维护,由于不同产品、不 同厂家造成功能类似而接口不相同情况下的解决方案,有点亡羊补牢的感觉。
优点
能提高类的透明性和复用,现有的类复用但不需要改变。
目标类和适配器类解耦,提高程序的扩展性。
在很多业务场景中符合开闭原则。
缺点
适配器编写过程需要全面考虑,可能会增加系统的复杂性。
增加代码阅读难度,降低代码可读性,过多使用适配器会使系统代码变得凌乱。
使用建议
能够重构就优先考虑重构,尽量不要使用适配器模式,毕竟业务复杂时代码看起来会很恶心。
代码实现
(实例一)媒体播放器适配器实现:
类图:
代码:
package com.knowledge.system.software_design_pattern.adapter_pattern.myself_instance;
public interface MediaPlayer {
public void play(String audioType,String fileName);
}
package com.knowledge.system.software_design_pattern.adapter_pattern.myself_instance;
public interface AdvancedMediaPlayer {
public void playVlc(String fileName);
public void playMp4(String fileName);
}
package com.knowledge.system.software_design_pattern.adapter_pattern.myself_instance;
public class Mp4Player implements AdvancedMediaPlayer {
@Override
public void playVlc(String fileName) {
}
@Override
public void playMp4(String fileName) {
System.out.println("Playing mp4 file. Name: "+ fileName);
}
}
package com.knowledge.system.software_design_pattern.adapter_pattern.myself_instance;
public class VlcPlayer implements AdvancedMediaPlayer {
@Override
public void playVlc(String fileName) {
System.out.println("Playing vlc file. Name: "+ fileName);
}
@Override
public void playMp4(String fileName) {
}
}
package com.knowledge.system.software_design_pattern.adapter_pattern.myself_instance;
public class MediaAdapter implements MediaPlayer {
AdvancedMediaPlayer advancedMusicPlayer;
public MediaAdapter(String audioType){
if(audioType.equalsIgnoreCase("vlc") ){
advancedMusicPlayer = new VlcPlayer();
} else if (audioType.equalsIgnoreCase("mp4")){
advancedMusicPlayer = new Mp4Player();
}
}
@Override
public void play(String audioType, String fileName) {
if(audioType.equalsIgnoreCase("vlc")){
advancedMusicPlayer.playVlc(fileName);
}else if(audioType.equalsIgnoreCase("mp4")){
advancedMusicPlayer.playMp4(fileName);
}
}
}
package com.knowledge.system.software_design_pattern.adapter_pattern.myself_instance;
public class AudioPlayer implements MediaPlayer {
MediaAdapter mediaAdapter;
@Override
public void play(String audioType, String fileName) {
//播放 mp3 音乐文件的内置支持
if(audioType.equalsIgnoreCase("mp3")){
System.out.println("Playing mp3 file. Name: "+ fileName);
}
//mediaAdapter 提供了播放其他文件格式的支持
else if(audioType.equalsIgnoreCase("vlc")
|| audioType.equalsIgnoreCase("mp4")){
mediaAdapter = new MediaAdapter(audioType);
mediaAdapter.play(audioType, fileName);
}
else{
System.out.println("Invalid media. "+
audioType + " format not supported");
}
}
}
package com.knowledge.system.software_design_pattern.adapter_pattern.myself_instance;
public class AdapterPatternDemo {
public static void main(String[] args) {
AudioPlayer audioPlayer=new AudioPlayer();
audioPlayer.play("mp3", "beyond the horizon.mp3");
audioPlayer.play("mp4", "alone.mp4");
audioPlayer.play("vlc", "far far away.vlc");
audioPlayer.play("avi", "mind me.avi");
}
}
(实例二)扩展登录方式的适配器实现:
简单实现:
package com.knowledge.system.software_design_pattern.adapter_pattern.course_instance;
import lombok.Data;
@Data
public class Member {
private String username;
private String password;
private String mid;
private String info;
}
package com.knowledge.system.software_design_pattern.adapter_pattern.course_instance;
import lombok.Data;
@Data
public class ResultMsg {
private int code;
private String msg;
private Object data;
public ResultMsg() {}
public ResultMsg(int code, String msg, Object data) {
this.code = code;
this.msg = msg;
this.data = data;
}
}
package com.knowledge.system.software_design_pattern.adapter_pattern.course_instance;
public class SignService {
public ResultMsg regist(String username,String password){
return new ResultMsg(200,"注册成功",new Member());
}
public ResultMsg login(String username,String password){
return null;
}
}
package com.knowledge.system.software_design_pattern.adapter_pattern.course_instance;
public class SignForThreadService extends SignService{
public ResultMsg loginForQQ(String openId){
return loginForRegist(openId,null);
}
public ResultMsg loginForWechat(String openId){
return null;
}
public ResultMsg loginForToken(String openId){
return null;
}
public ResultMsg loginForTelphne(String openId){
return null;
}
public ResultMsg loginForRegist(String username, String passwore) {
super.regist(username,null);
return super.login(username,null);
}
}
package com.knowledge.system.software_design_pattern.adapter_pattern.course_instance;
import com.alibaba.fastjson.JSON;
/**
* 0.简介:将一个类的一个接口转换成客户期望的另一个接口
* 0.1 已经存在的类,它的方法和需求不匹配(方法结果相同或相似)的情况。
* 0.2 适配器模式不是软件设计阶段考虑的设计模式,是随着软件维护,由于不同产品、不 同厂家造成功能类似而接口不相同情况下的解决方案。有点亡羊补牢的感觉。
* 1.源码实例:adapter结尾
*/
public class Test {
public static void main(String[] args) {
System.out.println("测试适配器模式");
SignForThreadService signForThreadService=new SignForThreadService();
ResultMsg msg=signForThreadService.loginForQQ("dafkjahgjkahd");
System.out.println(JSON.toJSON(msg));
}
}
引入适配器:
类图:
代码:
package com.knowledge.system.software_design_pattern.adapter_pattern.course_instance.adapter;
import com.knowledge.system.software_design_pattern.adapter_pattern.course_instance.ResultMsg;
public interface LoginAdapter {
boolean support(Object adapter);
ResultMsg login(String id,Object adapter);
}
package com.knowledge.system.software_design_pattern.adapter_pattern.course_instance.adapter;
import com.knowledge.system.software_design_pattern.adapter_pattern.course_instance.ResultMsg;
public interface IPassportForThird {
ResultMsg loginForQQ(String id);
ResultMsg loginForWechat(String id);
ResultMsg loginForToken(String token);
ResultMsg loginForTelphone(String telphone,String code);
ResultMsg loginForRegist(String username,String passport);
}
package com.knowledge.system.software_design_pattern.adapter_pattern.course_instance.adapter;
import com.knowledge.system.software_design_pattern.adapter_pattern.course_instance.ResultMsg;
public class LoginForQQAdapter implements LoginAdapter {
@Override
public boolean support(Object adapter) {
return adapter instanceof LoginForQQAdapter;
}
@Override
public ResultMsg login(String id, Object adapter) {
return new ResultMsg(200,"登录成功","success");
}
}
package com.knowledge.system.software_design_pattern.adapter_pattern.course_instance.adapter;
import com.knowledge.system.software_design_pattern.adapter_pattern.course_instance.ResultMsg;
public class LoginForTelAdapter implements LoginAdapter {
@Override
public boolean support(Object adapter) {
return adapter instanceof LoginForTelAdapter;
}
@Override
public ResultMsg login(String id, Object adapter) {
return null;
}
}
package com.knowledge.system.software_design_pattern.adapter_pattern.course_instance.adapter;
import com.knowledge.system.software_design_pattern.adapter_pattern.course_instance.ResultMsg;
public class LoginForTokenAdapter implements LoginAdapter {
@Override
public boolean support(Object adapter) {
return adapter instanceof LoginForTokenAdapter;
}
@Override
public ResultMsg login(String id, Object adapter) {
return null;
}
}
package com.knowledge.system.software_design_pattern.adapter_pattern.course_instance.adapter;
import com.knowledge.system.software_design_pattern.adapter_pattern.course_instance.ResultMsg;
public class LoginForWechatAdapter implements LoginAdapter{
@Override
public boolean support(Object adapter) {
return adapter instanceof LoginForWechatAdapter;
}
@Override
public ResultMsg login(String id, Object adapter) {
return null;
}
}
package com.knowledge.system.software_design_pattern.adapter_pattern.course_instance.adapter;
import com.knowledge.system.software_design_pattern.adapter_pattern.course_instance.ResultMsg;
public class PassportForThirdAdapter extends SignService implements IPassportForThird{
@Override
public ResultMsg loginForQQ(String id) {
return processLogin(id,LoginForQQAdapter.class);
}
@Override
public ResultMsg loginForWechat(String id) {
return processLogin(id,LoginForWechatAdapter.class);
}
@Override
public ResultMsg loginForToken(String token) {
return processLogin(token,LoginForTokenAdapter.class);
}
@Override
public ResultMsg loginForTelphone(String telphone, String code) {
return processLogin(telphone,LoginForTelAdapter.class);
}
@Override
public ResultMsg loginForRegist(String username, String passport) {
super.regist(username,null);
return super.login(username,null);
}
private ResultMsg processLogin(String key,Class<? extends LoginAdapter> clazz){
try {
LoginAdapter adapter=clazz.newInstance();
if(adapter.support(adapter)){
return adapter.login(key,adapter);
}else{
return null;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
package com.knowledge.system.software_design_pattern.adapter_pattern.course_instance.adapter;
import com.knowledge.system.software_design_pattern.adapter_pattern.course_instance.Member;
import com.knowledge.system.software_design_pattern.adapter_pattern.course_instance.ResultMsg;
public class SignService {
public ResultMsg regist(String username,String password){
return new ResultMsg(200,"注册成功",new Member());
}
public ResultMsg login(String username,String password){
return null;
}
}
package com.knowledge.system.software_design_pattern.adapter_pattern.course_instance.adapter;
import com.alibaba.fastjson.JSON;
import com.knowledge.system.software_design_pattern.adapter_pattern.course_instance.ResultMsg;
public class Test {
public static void main(String[] args) {
IPassportForThird passportForThird=new PassportForThirdAdapter();
ResultMsg msg=passportForThird.loginForQQ("1");
System.out.println(JSON.toJSONString(msg));
}
}