设计模式面试题(中)
结构型设计模式有哪些?
模式 | 描述 |
---|---|
适配器模式 | 封装对象,并提供不同的接口。 |
桥接模式 | 将抽象部分和实现部分分离,让他们独立的变化。 |
装饰模式 | 包装一个对象,提供新的行为。 |
组合模式 | 客户用一致的方式处理对象集合和单个对象。 |
外观模式 | 简化一群类的接口。 |
享元模式 | 运用共享技术有效的支持大量细粒度的对象。 |
代理模式 | 包装对象,以控制对此对象的访问。 |
什么是适配器模式?
定义
将一个类里面的方法转换成客户希望的另外一个方法,使得原来由于方法不兼容而不能够一起工作的那些类能够一起工作。
优缺点
优点
- 客户端通过适配器可以透明的调用目标方法。
- 复用了现存的方法,程序员不需要修改原有的代码而重用现有的适配者类。
- 将目标和适配者解耦,解决了目标类和适配者类接口不一致的问题。
缺点
- 对于适配器而言,更换适配器的实现过程比较复杂。
- 滥用适配器模式会让系统变得非常零乱。
代码实现
package net.haicoder.adapter;
/**
* 前期只有保险资源订单方法
*/
public class InsuranceCreate {
public void createInsuranceOrder() {
System.out.println("嗨客网 (www.haicoder.net)");
System.out.println("创建保险订单成功");
}
}
package net.haicoder.adapter;
public interface AdvancedOrderCreate {
/**
* 创建酒店订单
*/
void createHoTelOrder();
/**
* 创建机票订单
*/
void createFlightOrder();
}
package net.haicoder.adapter;
/**
* 创建酒店订单
*/
public class HotelCreate implements AdvancedOrderCreate {
public void createHoTelOrder() {
System.out.println("嗨客网 (www.haicoder.net)");
System.out.println("创建酒店订单成功");
}
public void createFlightOrder() {
}
}
package net.haicoder.adapter;
/**
* 创建机票订单
*/
public class FlightOrderCreate implements AdvancedOrderCreate {
public void createHoTelOrder() {
}
public void createFlightOrder() {
System.out.println("嗨客网 (www.haicoder.net)");
System.out.println("创建机票订单成功");
}
}
package net.haicoder.adapter;
public class OrderCreateAdapter {
AdvancedOrderCreate advancedOrderCreate;
public OrderCreateAdapter(String orderType) {
if ("flight".equals(orderType)) {
advancedOrderCreate = new FlightOrderCreate();
} else if ("hotel".equals(orderType)) {
advancedOrderCreate = new HotelCreate();
}
}
public void createOrder(String orderType) {
if ("flight".equals(orderType)) {
advancedOrderCreate.createFlightOrder();
} else if ("hotel".equals(orderType)) {
advancedOrderCreate.createHoTelOrder();
} else {
System.out.println("嗨客网 (www.haicoder.net)");
System.out.println("对不起,您创建的订单类型目前没有开通,敬请期待。。。");
}
}
}
package net.haicoder.adapter;
public class OrderCreate {
public void createOrder(String orderType) {
if ("insurcnce".equals(orderType)) {
new InsuranceCreate().createInsuranceOrder();
} else {
OrderCreateAdapter orderCreateAdapter = new OrderCreateAdapter(orderType);
orderCreateAdapter.createOrder(orderType);
}
}
}
package net.haicoder.adapter;
public class TestMain {
public static void main(String[] args) {
OrderCreate orderCreate = new OrderCreate();
orderCreate.createOrder("hotel");
}
}
参考文章:原文链接
什么是桥接模式?
定义
将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。又称为柄体模式或接口模式。
优缺点
优点
- 抽象与实现分离,扩展能力强。
- 实现细节对客户透明。
- 减少了因为继承带来的类爆炸。
缺点
- 聚合关系建立在抽象层,要求开发者针对抽象化设计与编程,增加了系统理解与设计难度。
代码实现
package net.haicoder.bridge;
public abstract class InsuranceResourceService {
public abstract void isBuyInsurance();
}
package net.haicoder.bridge;
public class BuyInsuranceResource extends InsuranceResourceService {
public void isBuyInsurance() {
System.out.println("Yes , I need Insurance");
}
}
package net.haicoder.bridge;
public class NotBuyInsuranceResource extends InsuranceResourceService {
public void isBuyInsurance() {
System.out.println("Sorry , I do not need Insurance");
}
}
package net.haicoder.bridge;
public abstract class AbstractCreateOrder {
protected InsuranceResourceService insuranceResourceService;
public abstract void createOrder();
public void setInsuranceResourceService(InsuranceResourceService insuranceResourceService) {
this.insuranceResourceService = insuranceResourceService;
}
}
package net.haicoder.bridge;
public class FlightCreateOrder extends AbstractCreateOrder {
public void createOrder() {
insuranceResourceService.isBuyInsurance();
System.out.println("创建机票订单");
}
}
package net.haicoder.bridge;
public class HotelCreateOrder extends AbstractCreateOrder {
public void createOrder() {
insuranceResourceService.isBuyInsurance();
System.out.println("创建酒店订单");
}
}
package net.haicoder.bridge;
public class TestMain {
public static void main(String[] args) {
System.out.println("海客网(www.haicoder.net)");
InsuranceResourceService buyInsurance = new BuyInsuranceResource();
AbstractCreateOrder createOrder = new FlightCreateOrder();
createOrder.setInsuranceResourceService(buyInsurance);
createOrder.createOrder();
System.out.println("=========华丽的分割线===========");
InsuranceResourceService notBuyInsurance = new NotBuyInsuranceResource();
AbstractCreateOrder hotelCreateOrder = new HotelCreateOrder();
hotelCreateOrder.setInsuranceResourceService(notBuyInsurance);
hotelCreateOrder.createOrder();
}
}
参考文章:原文链接
什么是装饰模式?
定义
在不改变现有对象结构的情况下,动态的给该对象增加一些额外的功能的模式。
优缺点
优点
- 装饰模式扩展对象的功能比采用继承的方式更加灵活。
- 可以设计出多个不同的具体装饰类,创造出多个不同的行为的组合。
缺点
- 装饰模式增加了许多子类,如果过度的使用的化会使程序变得更加复杂。
- 装饰模式会导致设计中出现许多小类,如果过度使用,会使程序变得更加复杂。
代码实现
package net.haicoder.decorator;
/**
* 基类创建订单
*/
public abstract class BaseCreateOrder {
public abstract void createOrder();
}
package net.haicoder.decorator;
public class TourOrderCreate extends BaseCreateOrder {
public void createOrder() {
System.out.println("嗨客网(www.haicoder.ner)");
System.out.println("创建度假订单");
}
}
package net.haicoder.decorator;
public abstract class Decorator extends BaseCreateOrder {
private BaseCreateOrder createOrder;
public Decorator(BaseCreateOrder createOrder) {
this.createOrder = createOrder;
}
public void createOrder() {
createOrder.createOrder();
}
}
package net.haicoder.decorator;
/**
* 具体装饰角色,负责给组件添加职责
* 把被传递的对象包装
*/
public class InsuranceDecorator extends Decorator {
public InsuranceDecorator(BaseCreateOrder createOrder) {
super(createOrder);
}
public void createOrder() {
super.createOrder();
System.out.println("创建订单的时候,添加了保险资源");
}
}
package net.haicoder.decorator;
public class TestMain {
public static void main(String[] args) {
BaseCreateOrder createOrder = new TourOrderCreate();
InsuranceDecorator insuranceDecorator = new InsuranceDecorator(createOrder);
insuranceDecorator.createOrder();
}
}
参考文章:原文链接
什么是组合模式?
定义
组合模式将对象组合成树形结构以表示 “部分-整体” 的层次结构。组合模式使得用户可以使用一致的方法操作单个对象和组合对象。
优缺点
优点
- 组合模式使得客户端代码可以一致地处理单个对象和组合对象,无须关系自己处理的是单个对象还是组合对象,这简化的客户端代码。
- 更容易在组合体内加入新的对象,客户端不会因为加入新的对象而更改源代码,满足开闭原则。
缺点
- 客户端需要花更多的时间理清类之间的层次关系。
- 不容易限制容器中的构建。
- 不容易用继承的方法来增加构建的新功能。
- 比较难限制组合中的组件类型。
代码实现
package net.haicoder.composite;
import java.util.List;
public interface RootProduct {
List<RootProduct> allProducts();
boolean addProduct(RootProduct product);
boolean addProducts(List<RootProduct> products);
boolean removeProduct(RootProduct product);
}
package net.haicoder.composite;
import java.util.ArrayList;
import java.util.List;
public class ProductCategory implements RootProduct {
private Integer id;
private String name;
private List<RootProduct> rootProducts = new ArrayList<RootProduct>();
public ProductCategory(Integer id, String name) {
this.id = id;
this.name = name;
}
public List<RootProduct> allProducts() {
return this.rootProducts;
}
public boolean addProduct(RootProduct product) {
return rootProducts.add(product);
}
public boolean addProducts(List<RootProduct> products) {
return rootProducts.addAll(products);
}
public boolean removeProduct(RootProduct product) {
return rootProducts.remove(product);
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<RootProduct> getRootProducts() {
return rootProducts;
}
public void setRootProducts(List<RootProduct> rootProducts) {
this.rootProducts = rootProducts;
}
}
package net.haicoder.composite;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
public class Product implements RootProduct {
private Integer id;
private String name;
private String model;
private BigDecimal price;
public Product(Integer id, String name, String model, BigDecimal price) {
this.id = id;
this.name = name;
this.model = model;
this.price = price;
}
public List<RootProduct> allProducts() {
List<RootProduct> rootProducts = new ArrayList<RootProduct>();
rootProducts.add(this);
return rootProducts;
}
public boolean addProduct(RootProduct product) {
throw new RuntimeException("不支持此方法");
}
public boolean addProducts(List<RootProduct> products) {
throw new RuntimeException("不支持此方法");
}
public boolean removeProduct(RootProduct product) {
throw new RuntimeException("不支持此方法");
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
}
package net.haicoder.composite;
import com.alibaba.fastjson.JSONObject;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
public class TestMain {
public static void main(String[] args) {
RootProduct rootProducts = new ProductCategory(1, "根目录");
RootProduct fruitsCategory = new ProductCategory(100, "水果类");
RootProduct winkCategory = new ProductCategory(200, "白酒类");
List<RootProduct> categorys = new ArrayList<RootProduct>();
categorys.add(fruitsCategory);
categorys.add(winkCategory);
rootProducts.addProducts(categorys);
Product fruidProduct = new Product(1, "苹果", "KG", new BigDecimal(20));
Product yanghe = new Product(2, "洋河", "450ML", new BigDecimal(200));
fruitsCategory.addProduct(fruidProduct);
winkCategory.addProduct(yanghe);
System.out.println("嗨客网(www.haicoder.net)");
System.out.println(JSONObject.toJSONString(rootProducts));
}
}
参考文章:原文链接
什么是外观模式?
定义
为多个复杂的子系统提供一个一致的接口,从而使这些子系统更加容易的被访问。外部系统访问的时候,只会关心该接口,不会关注内部细节。
优缺点
优点
- 实现了子系统与客户端系统之间的松耦合关系。
- 客户端屏蔽了子系统,减少了对各个子系统的引用与维护,使得客户端使用起来更加方便。
缺点
- 不能很好地限制客户使用子系统类。
- 增加新的子系统需要修改外观类或者客户端的源码,违背了 “开闭原则”。
代码实现
package net.haicoder.facade;
public class FlightResource {
public void createFlightResource() {
System.out.println("创建机票资源");
}
}
package net.haicoder.facade;
public class InsuranceResource {
public void createInsurance() {
System.out.println("创建保险资源");
}
}
package net.haicoder.facade;
public class OrderCreate {
private InsuranceResource insuranceResource = new InsuranceResource();
private FlightResource flightResource = new FlightResource();
public void createOrder() {
insuranceResource.createInsurance();
flightResource.createFlightResource();
}
}
package net.haicoder.facade;
public class TestMain {
public static void main(String[] args) {
OrderCreate orderCreate = new OrderCreate();
System.out.println("嗨客网(www.haicoder.net)");
orderCreate.createOrder();
}
}
参考文章:原文链接
什么是享元模式?
定义
享元模式,运用共享技术,有效地支持大量细粒度的对象的复用。
优缺点
优点
大大减少了对象的创建,降低了程序内存的占用,提高效率。
缺点
提高了系统的复杂度。需要区分内蕴状态(享元内部,不会随着环境的改变而有所不同)和外蕴状态(随着环境的改变而改变,不可共享)。
代码实现
package net.haicoder.flyweight;
import java.util.LinkedList;
public class MyDataSource {
private LinkedList<Integer> dataSources = new LinkedList<Integer>();
//初始化连接数量
public MyDataSource() {
//一次性创建10个连接
for (int i = 0; i < 4; i++) {
try {
Integer connection = i;
//1、装载sqlserver驱动对象
System.out.println("-----加载驱动");
//2、通过JDBC建立数据库连接
System.out.println("----建立数据库连接");
//3、将连接加入连接池中
dataSources.add(connection);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public Integer getConnection() {
//取出连接池中一个连接
final Integer conn = dataSources.removeFirst(); // 删除第一个连接返回
System.out.println("获取一个连接");
return conn;
}
//将连接放回连接池
public void releaseConnection(Integer conn) {
System.out.println("释放连接");
dataSources.add(conn);
}
}
package net.haicoder.flyweight;
public class TestMain {
public static void main(String[] args) {
System.out.println("嗨客网(www.haicoder.net)");
MyDataSource myDataSource = new MyDataSource();
Integer coon = myDataSource.getConnection();
myDataSource.releaseConnection(coon);
}
}
参考文章:原文链接
什么是代理模式?
定义
一个类代表另一个类的功能,被代表的类不会对外部提供访问路径,只有代理类提供。
优缺点
优点
- 代理模式在客户端与目标对象之间起到了一个中介作用和保护目标对象的作用。
- 代理对象可以扩展目标对象的功能。
- 将客户端和目标对象进行了分离,在一定程度上降低了系统间的耦合度。
缺点
- 增加了系统的复杂度,客户端只能够看到代理类。
- 会出现大量的重复代码。
代码实现
package net.haicoder.proxy;
public interface IOrderService {
Integer createOrder(Object param);
}
OrderCreate.java 代码如下:
package net.haicoder.proxy;
public class OrderCreate implements IOrderService {
public Integer createOrder(Object param) {
System.out.println("创建订单");
return 1;
}
}
package net.haicoder.proxy;
public class OrderCreateProxy implements IOrderService {
OrderCreate orderCreate;
public OrderCreateProxy() {
orderCreate = new OrderCreate();
}
public Integer createOrder(Object param) {
before();
Object object = null;
orderCreate.createOrder(object);
after();
return null;
}
private void before() {
System.out.println("创建订单前");
}
private void after() {
System.out.println("创建订单后");
}
}
package net.haicoder.proxy;
public class TestMain {
public static void main(String[] args) {
System.out.println("嗨客网(www.haicoder.net)");
OrderCreateProxy orderCreateProxy = new OrderCreateProxy();
Object param = null;
orderCreateProxy.createOrder(param);
}
}
参考文章:原文链接