适配器模式
定义:
适配器模式将一个类的接口,转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。
这个模式可以通过创建适配器进行接口转换,让不兼容的接口变成兼容。这可以让客户从实现的接口解耦。
适配器模式充满着良好的OO设计原则:使用对象组合,以修改的接口包装被适配者,这种做法还有额外的优点: 被适配者的任何子类,都可以搭配着适配器使用。
类图:
`
角色:
目标接口(Target):客户所期待的接口。目标可以是具体德尔或抽象的类,也可以是接口。
被适配类(Adaptee):需要适配的类或者适配者类。
适配器(Adapter):通过包装一个需要适配的对象,把原接口转换成目标接口。
对象和类适配器:
适配器模式分为两种:对象适配器和类适配器。采用组合的方式是对象适配器,通过继承方式实现的适配器是类适配器。
优缺点:
优点:
1. 通过适配器,客户端可以调用同一接口,因而对客户端来说是透明的。
2. 复用了现有的类,解决了现存类和复用环境要求不一致的问题。
3. 将目标类和适配者类解耦,通过引入一个适配器类重用现有的适配者类,而无需修改原有代码。
4. 一个对象适配器可以把多个不同的适配者类适配到同一个目标,也就是说,同一个适配器可以把适配者类和它的子类都是配到目标接口。
缺点:
对于对象适配器来说,更换适配器的实现过程比较复杂。
适用场景:
1. 系统需要使用现有的类,但是这些类的接口不符合系统的接口
2. 两个类所做的事情相同或相似,但接口不同时。
3. 旧的系统开发的类已经实现了一些功能,但是客户端却只能以另外接口的形式访问,但我们不希望手动更改原有类的时候。
4. 使用第三方组件,组件接口定义和自己定义的不同,不希望修改自己的接口,但是要使用第三方组件接口的功能。(很常用的场景就是我们封装接口时,注入几个service,然后合并成一个BO对象返回,这就是适配器的经典例子)
和其他模式的区别
装饰器:不改变接口,但加入职责。
适配器:讲一个接口转成另一个接口
外观模式:使接口变得简单。
实例
Target:目标接口
* Descrption: 目标接口,需要根据sku查询商品基本信息,返回一个ProductInfo对象, * 只包含sku,name和star三个属性,其他的不需要 * To change this template use File | Settings | File Templates. */ public interface Target { public ProductInfo getProductInfoBySku(String sku); } |
ProductService:被适配类,商品服务类
package com.mylearn.designmodel.adapter.example; /** * Created by IntelliJ IDEA. * User: yingkuohao * Date: 14-2-10 * Time: 下午3:17 * CopyRight:360buy * Descrption: 商品信息服务类,提供商品的一些接口 * To change this template use File | Settings | File Templates. */ public class ProductService { /** * 根据sku获取商品信息, * * @param sku * @return */ public Product getProductById(String sku) { Product product = new Product(); product.setSku(sku); product.setName(sku + "name"); product.setPrice(String.valueOf(Math.random())); product.setColor("yellow"); return product; } /** * 商品实体类,包含商品的基本信息,如名称,价格,颜色等 */ class Product { private String sku; private String name; private String price; private String color; public String getSku() { return sku; } public void setSku(String sku) { this.sku = sku; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPrice() { return price; } public void setPrice(String price) { this.price = price; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } } } |
CommentService:被适配类,评论服务类
package com.mylearn.designmodel.adapter.example; /** * Created by IntelliJ IDEA. * User: yingkuohao * Date: 14-2-10 * Time: 下午3:20 * CopyRight:360buy * Descrption: 评论服务类,根据sku可以拿到商品的评论信息,包括sku,星级,评论内容,优点,缺点等 * To change this template use File | Settings | File Templates. */ public class CommentService { /** * 根据sku获取评论信息 * * @param sku * @return */ public Comment getCommentBySku(String sku) { Comment comment = new Comment(); comment.setSku(sku); comment.setStar(String.valueOf(Math.random())); comment.setComment("不错,送货速度真快!"); comment.setGood("物美价廉!"); comment.setWeak("暂时还未发现缺点"); return comment; } /** * 评论对象 */ class Comment { private String sku; private String star; private String comment; private String good; private String weak; public String getSku() { return sku; } public void setSku(String sku) { this.sku = sku; } public String getStar() { return star; } public void setStar(String star) { this.star = star; } public String getComment() { return comment; } public void setComment(String comment) { this.comment = comment; } public String getGood() { return good; } public void setGood(String good) { this.good = good; } public String getWeak() { return weak; } public void setWeak(String weak) { this.weak = weak; } } } |
AdapterService:适配器类
package com.mylearn.designmodel.adapter.example; /** * Created by IntelliJ IDEA. * User: yingkuohao * Date: 14-2-10 * Time: 下午3:25 * CopyRight:360buy * Descrption: 适配器类,组合 productService和 commentService * To change this template use File | Settings | File Templates. */ public class AdapterService implements Target { private ProductService productService; private CommentService commentService; /** * 这里通过构造方法注入,实际中通过spring注进来 * @param productService * @param commentService */ public AdapterService(ProductService productService, CommentService commentService) { this.productService = productService; this.commentService = commentService; } public ProductInfo getProductInfoBySku(String sku) { //1. 根据sku获取product信息 ProductService.Product product = productService.getProductById(sku); //2. 根据sku获取comment信息 CommentService.Comment comment = commentService.getCommentBySku(sku); //3. 重新组装目标对象,返回 ProductInfo productInfo = new ProductInfo(); productInfo.setSku(sku); productInfo.setName(product.getName()); productInfo.setStar(comment.getStar()); return productInfo; //To change body of implemented methods use File | Settings | File Templates. } public ProductService getProductService() { return productService; } public void setProductService(ProductService productService) { this.productService = productService; } public CommentService getCommentService() { return commentService; } public void setCommentService(CommentService commentService) { this.commentService = commentService; } } |
ProductInfo:目标实体对象
package com.mylearn.designmodel.adapter.example; /** * Created by IntelliJ IDEA. * User: yingkuohao * Date: 14-2-10 * Time: 下午3:24 * CopyRight:360buy * Descrption: 目标实体对象 * To change this template use File | Settings | File Templates. */ public class ProductInfo { private String sku; private String name; private String star; public String getSku() { return sku; } public void setSku(String sku) { this.sku = sku; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getStar() { return star; } public void setStar(String star) { this.star = star; } @Override public String toString() { return "ProductInfo{" + "sku='" + sku + '\'' + ", name='" + name + '\'' + ", star='" + star + '\'' + '}'; } } |
Client:客户端
public class Client { public static void main(String args[]) { String sku = "1"; ProductService productService = new ProductService(); CommentService commentService = new CommentService(); Target target = new AdapterService(productService, commentService); ProductInfo productInfo = target.getProductInfoBySku(sku); System.out.println(productInfo.toString()); } } |