一些设计模式的感想(上)
本篇简单描述6个设计模式,分别是:适配器模式(Adapter Pattern),装饰器模式(Decorator Pattern),外观模式(Facade Pattern),策略模式(Strategy Pattern),模板模式(Template Pattern),迭代器模式(Iterator Pattern)
1.适配器模式(Adapter Pattern)
简单来说,适配器模式是一种结构型模式,可以作为桥梁将两个独立接口功能连接起来。我们日常生活中的读卡器,耳机转换器都可以看做一种适配器。
作用:它可以使得原本相互不兼容的类可以通过适配器一起工作,推荐使用继承或者依赖的方式来调用适配器。
优点:可以使两个无关的类一起运行,提高了类的复用度。
缺点:过多使用会使代码编写的逻辑性散乱,更容易出现逻辑性错误。
示例:
public interface MotorVehicle {
public void travel(String trans, String transName);
}
public interface NotMotorVehicle {
public void BikeTravel(String transName);
}
public class Bike implements NotMotorVehicle{
public void BikeTravel(String transName) {
System.out.println(transName + "行驶在自行车道");
}
}
public class VehicleAdapter implements MotorVehicle {
NotMotorVehicle nmvehicle;
@Override
public void travel(String trans, String transName) {
if(trans.equals("Bike"))
{
nmvehicle = new Bike();
nmvehicle.BikeTravel(transName);
}
else
System.out.println("不支持这种交通工具!");
}
}
public class Car implements MotorVehicle {
VehicleAdapter vehicleAdapter = new VehicleAdapter();
@Override
public void travel(String trans, String transName) {
if(trans.equals("Car"))
System.out.println(transName + "行驶在马路上");
else
vehicleAdapter.travel(trans, transName);
}
}
测试:
public class VehicleTest {
@Test
public void testVehicleTest()
{
Car vehicle = new Car();
vehicle.travel("Car", "福特");
vehicle.travel("Bike", "美捷达");
vehicle.travel("Motor", "摩托");
}
}
结果:
2.装饰器模式(Decorator Pattern)
装饰器模式可以在不改变被装饰类结构的情况下为其添加新的功能。
作用:为了避免新添加少量功能而多次继承,可以使用装饰器为其灵活的添加新的功能。
优点:装饰类和被装饰类相互独立,降低了代码耦合度,并且由于使用起来灵活可以动态扩展一个类的功能,并且提高代码的复用性。
缺点:使用起来会使代码变得更复杂
示例:
public interface Graphics {
public void draw();
}
public class Circle implements Graphics {
@Override
public void draw() {
System.out.println("圆");
}
}
public class GraphicsDecorator implements Graphics {
protected Graphics graphicsDecorator;
public GraphicsDecorator(Graphics g) {
this.graphicsDecorator = g;
}
@Override
public void draw() {
graphicsDecorator.draw();
}
}
public class BlueDecorator extends GraphicsDecorator{
public BlueDecorator(Graphics graphicsDecorator)
{
super(graphicsDecorator);
}
@Override
public void draw() {
drawBlue(graphicsDecorator);
graphicsDecorator.draw();
}
private void drawBlue(Graphics decoratedShape){
System.out.print("蓝色的");
}
}
测试:
public class TestGraphics {
@Test
public void testGraphics()
{
Graphics circle = new Circle();
GraphicsDecorator circleDecorator = new BlueDecorator(new Circle());
circle.draw();
circleDecorator.draw();
}
}
结果:
3.外观模式(Facade Pattern)
向客户端提供一个客户端可以使用的接口,简化其操作并隐藏程序的复杂性。
作用:可以降低客户端使用时的复杂操作,简化客户端的使用,并且保护代码内部结构不暴露。
优点:提高了灵活性与程序安全性
缺点:不符合开闭原则,修改起来很麻烦,增加了代码的耦合性。
示例:
public interface Vehicle {
public void trans();
}
public class Plane implements Vehicle {
@Override
public void trans() {
System.out.println("飞机在天上");
}
}
public class Train implements Vehicle {
@Override
public void trans() {
System.out.println("火车在地上");
}
}
public class Ship implements Vehicle {
@Override
public void trans() {
System.out.println("轮船在海上");
}
}
public class SelectVehicle {
private Plane plane;
private Train train;
private Ship ship;
public SelectVehicle()
{
plane = new Plane();
train = new Train();
ship = new Ship();
}
public void transPlane() {
plane.trans();
}
public void transTrain() {
train.trans();
}
public void transShip() {
ship.trans();
}
}
测试:
public class TestFacade {
@Test
public void testFacade()
{
SelectVehicle facade = new SelectVehicle();
facade.transPlane();
facade.transTrain();
facade.transShip();
}
}
结果:
4.策略模式(Strategy Pattern)
在程序运行时,一个类的内部实现或者算法可以随客户端的使用不同而更改。
作用:将不同的算法进行封装并使它们可相互替代,便于在不同需求时使用。
优点:可以在避免使用多重if语句判断得情况下,自由切换使用的算法,且在扩展是,可以避免修改过多代码,提高代码的可扩展性。
示例:
public interface Strategy {
public int Operation(int number1, int number2);
}
public class Add implements Strategy {
@Override
public int Operation(int number1, int number2) {
return number1 + number2;
}
}
public class Sub implements Strategy {
@Override
public int Operation(int number1, int number2) {
return number1 - number2;
}
}
public class Select {
private Strategy strategy;
public Select(Strategy strategy) {
this.strategy = strategy;
}
public int SelectStrategy(int num1, int num2){
return strategy.Operation(num1, num2);
}
}
测试:
public class TestStrategy {
@Test
public void testFacade()
{
Select strategy1 = new Select(new Add());
Select strategy2 = new Select(new Sub());
System.out.println("42 + 37 = " + strategy1.SelectStrategy(42, 37));
System.out.println("12 - 7 = " + strategy2.SelectStrategy(12, 7));
}
}
结果:
5.模板模式(Template Pattern)
类似于框架,在抽象类中定义好其子类应该遵循的模板,并由子类添加细节实现不同的功能。为避免子类重写一般定义为final类型。
作用:可以在不改变一个算法大体骨架的情况下重写某些特定步骤来完成不同的功能。
优点:提高代码的复用性,将共用的部分进行封装,并将不同的部分基于封装进行扩展,易于修改。
示例:
public abstract class BoardGame {
abstract void initialize();
abstract void startPlay();
abstract void endPlay();
public final void play(){
initialize();
startPlay();
endPlay();
}
}
public class ChessGame extends BoardGame {
@Override
void initialize() {
System.out.println("初始化国际象棋");
}
@Override
void startPlay() {
System.out.println("开始国际象棋");
}
@Override
void endPlay() {
System.out.println("结束国际象棋");
}
}
public class GoGame extends BoardGame {
@Override
void initialize() {
System.out.println("初始化围棋");
}
@Override
void startPlay() {
System.out.println("开始围棋");
}
@Override
void endPlay() {
System.out.println("结束围棋");
}
}
测试:
public class TestTemplate {
@Test
public void testFacade()
{
BoardGame game1 = new ChessGame();
BoardGame game2 = new GoGame();
game1.play();
System.out.println();
game2.play();
}
}
结果:
6.迭代器模式(Iterator Pattern)
作用:可以在不知道集合对象内部表示的情况下顺序的访问其内部元素。
优点:将遍历集合功能单独抽象分离开来,降低代码耦合性,提高代码复用性。
缺点:一个新的集合类就需要一个对应的迭代器类,增加代码的复杂性。
示例:
public interface Iterator {
public boolean hasNext();
public Object next();
}
public interface Container {
public Iterator getIterator();
}
public class StrRepository implements Container {
public List<String> strs = new ArrayList<>();
{
strs.add("A");
strs.add("B");
strs.add("C");
strs.add("D");
strs.add("E");
};
@Override
public Iterator getIterator() {
return new StrIterator();
}
private class StrIterator implements Iterator {
int index;
@Override
public boolean hasNext() {
if(index < strs.size()){
return true;
}
return false;
}
@Override
public Object next() {
if(this.hasNext()){
return strs.get(index ++);
}
return null;
}
}
}
测试:
public class TestIterator {
@Test
public void testFacade()
{
StrRepository namesRepository = new StrRepository();
for(Iterator iter = namesRepository.getIterator(); iter.hasNext(); ){
String str = (String)iter.next();
System.out.println(str);
}
}
}
结果: