本篇简单描述7个设计模式,分别是:工厂模式(Factory Pattern),抽象工厂模式(Abstract Factory Pattern),代理模式(Proxy Pattern),观察者模式(Observer Pattern),访问者模式(Visitor Pattern),状态模式(State Pattern),备忘录模式(Memento Pattern)
工厂模式是 Java 中最常用的设计模式之一。通过使用工厂模式,我们可以在不对客户端暴露代码内部逻辑的情况下使用一个共同的新接口来创建新的对象。
作用:将对象的创建延迟到创建对象的接口子类里,通过调用工厂类进行
优点:调用者只需知道想要创建对象的名字即可进行对象的创建,无需暴露代码内部逻辑,并且这样的代码可扩展性高,只需添加一个新的工厂类即可支持一个新对象的创建
缺点:增加了程序的复杂度
示例:
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 VehicleFactory {
public Vehicle GetVehicle(String vehicleType)
{
if(vehicleType == null)
return null;
else if(vehicleType == "Plane")
return new Plane();
else if(vehicleType == "Train")
return new Train();
else if(vehicleType == "Ship")
return new Ship();
return null;
}
}
测试:
public class TestFactory {
@Test
public void testFacade()
{
VehicleFactory factory = new VehicleFactory();
Vehicle vehicle1 = factory.GetVehicle("Plane");
vehicle1.trans();
Vehicle vehicle2 = factory.GetVehicle("Train");
vehicle2.trans();
Vehicle vehicle3 = factory.GetVehicle("Ship");
vehicle3.trans();
}
}
抽象工厂模式是通过一个超级工厂创建其他工厂,每个被创建的工厂都能按照工厂模式创建对象。
作用:可以方便不同种类的多种对象的创建。
优点:可以保证客户端对对象的创建保持在同一种类
缺点:不易于扩展
示例:
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 interface BoardGame {
public void play();
}
public class ChessGame implements BoardGame {
@Override
public void play() {
System.out.println("这是象棋游戏");
}
}
public class GoGame implements BoardGame {
@Override
public void play() {
System.out.println("这是围棋游戏");
}
}
public abstract class AbstractFactory {
public abstract BoardGame getGame(String gameType);
public abstract Vehicle getVehicle(String vehicleType) ;
}
public class VehicleFactory extends AbstractFactory {
public Vehicle getVehicle(String vehicleType)
{
if(vehicleType == null)
return null;
else if(vehicleType.equals("Plane"))
return new Plane();
else if(vehicleType.equals("Train"))
return new Train();
else if(vehicleType.equals("Ship"))
return new Ship();
return null;
}
@Override
public BoardGame getGame(String gameType) {
return null;
}
}
public class GameFactory extends AbstractFactory {
public BoardGame getGame(String gameType)
{
if(gameType == null)
return null;
else if(gameType.equals("Chess"))
return new ChessGame();
else if(gameType.equals("Go"))
return new GoGame();
return null;
}
@Override
public Vehicle getVehicle(String vehicleType) {
return null;
}
}
public class Factory {
public static AbstractFactory getFactory(String choice){
if(choice.equalsIgnoreCase("Vehicle")){
return new VehicleFactory();
}
else if(choice.equalsIgnoreCase("Game")){
return new GameFactory();
}
return null;
}
}
测试:
@Test
public void testFacade()
{
AbstractFactory vehiclefactory = Factory.getFactory("Vehicle");
Vehicle vehicle1 = vehiclefactory.getVehicle("Plane");
vehicle1.trans();
Vehicle vehicle2 = vehiclefactory.getVehicle("Train");
vehicle2.trans();
Vehicle vehicle3 = vehiclefactory.getVehicle("Ship");
vehicle3.trans();
AbstractFactory gamefactory = Factory.getFactory("Game");
BoardGame game1 = gamefactory.getGame("Chess");
game1.play();
BoardGame game2 = gamefactory.getGame("Go");
game2.play();
}
}
在代理模式中,用一个一个类代表另一个类的功能,从而实现代理或者说是委托的效果。
作用:为其他对象提供一种代理来控制对这个对象的访问
优点:将功能进行分离,独立性高,易于扩展
缺点:使用时开销可能增大,并且实现复杂
示例:
public interface BoardGame {
public void play();
}
public class PlayChessGame implements BoardGame {
@Override
public void play() {
System.out.println("开始国际象棋");
System.out.println("结束国际象棋");
}
}
public class ChessGame implements BoardGame {
@Override
public void play() {
PlayChessGame playChessGame = new PlayChessGame();
System.out.println("初始化国际象棋");
playChessGame.play();
}
}
测试:
public class TestProxy {
@Test
public void testFacade()
{
BoardGame proxy = new ChessGame();
proxy.play();
}
}
观察者模式会在一个对象被修改时,自动通知使用它的对象。
作用:当一个对象的状态发生改变时,所有使用它的对象都得到通知并进行自动更新。
优点:有一套专门的触发机制
缺点:会耗费许多时间,并且在观察者和被观察者间有循环依赖可能导致系统崩溃。
示例:
public class Subject {
private List observers = new ArrayList();
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
notifyAllObservers();
}
public void attach(Observer observer){
observers.add(observer);
}
public void notifyAllObservers(){
for (Observer observer : observers) {
observer.update();
}
}
}
public abstract class Observer {
protected Subject subject;
public abstract void update();
}
public class BinaryObserver extends Observer {
public BinaryObserver(Subject subject){
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println( "二进制为: " + Integer.toBinaryString( subject.getState() ) );
}
}
public class HexaObserver extends Observer { //十六进制
public HexaObserver(Subject subject){
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println( "十六进制为: " + Integer.toHexString( subject.getState() ).toUpperCase() );
}
}
测试:
public class TestObserver {
@Test
public void ObserverTest()
{
Subject subject = new Subject();
new HexaObserver(subject);
new BinaryObserver(subject);
System.out.println("改变状态为: 15");
subject.setState(30);
System.out.println("改变状态为: 10");
subject.setState(11);
}
}
访问者模式通过使用一个访问者类,使得元素的执行算法可以随着访问者改变而改变。
作用:将数据结构与数据操作分离。
优点:符合单一职责原则,有着很高的可扩展性与灵活性
缺点:依赖了具体类而不是抽象类
示例:
public interface ArticlePart {
public void read(ArticlePartVisitor computerPartVisitor);
}
public class Title implements ArticlePart {
@Override
public void read(ArticlePartVisitor articlePartVisitor) {
articlePartVisitor.visit(this);
}
}
public class Text implements ArticlePart {
@Override
public void read(ArticlePartVisitor articlePartVisitor) {
articlePartVisitor.visit(this);
}
}
public class Summary implements ArticlePart {
@Override
public void read(ArticlePartVisitor articlePartVisitor) {
articlePartVisitor.visit(this);
}
}
public class Article implements ArticlePart {
ArticlePart[] parts;
public Article(){
parts = new ArticlePart[] {new Title(), new Text(), new Summary()};
}
@Override
public void read(ArticlePartVisitor articlePartVisitor) {
for (int i = 0; i < parts.length; i++) {
parts[i].read(articlePartVisitor);
}
articlePartVisitor.visit(this);
}
}
public interface ArticlePartVisitor {
public void visit(Article acticle);
public void visit(Title title);
public void visit(Text text);
public void visit(Summary summary);
}
public class ReadActicle implements ArticlePartVisitor {
@Override
public void visit(Article acticle) {
System.out.println("文章");
}
@Override
public void visit(Title title) {
System.out.println("标题");
}
@Override
public void visit(Text text) {
System.out.println("正文");
}
@Override
public void visit(Summary summary) {
System.out.println("总结");
}
}
测试:
public class TestVisitor {
@Test
public void VisitorTest(){
ArticlePart acticle = new Article();
acticle.read(new ReadActicle());
}
}
状态模式中,类的行为会随它的状态而改变的。
作用:可以在不使用大量if-else语句的情况下通过改变一个类的状态来改变一个类的行为
优点:将转换原则进行了封装,并且将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态
缺点:实现较为复杂,容易造成代码的混乱
示例:
public interface State {
public void open(Context context);
public void close(Context context);
}
public class OpenState implements State {
public void open(Context context) {
System.out.println(("无法开启"));
}
public void close(Context context) {
context.setState(new CloseState());
System.out.println("关闭");
}
}
public class CloseState implements State {
public void open(Context context) {
context.setState(new OpenState());
System.out.println("开启");
}
public void close(Context context) {
System.out.println(("无法关闭"));
}
}
public class Context {
private State state;
public void setState(State state) {
this.state = state;
}
public State getState() {
return state;
}
public void open() {
if (getState() instanceof CloseState) {
getState().open(this);
setState(new OpenState());
}else {
System.out.println(("已开启"));
}
}
public void close() {
if (getState() instanceof OpenState) {
getState().close(this);
setState(new CloseState());
}else {
System.out.println(("已关闭"));
}
}
}
测试:
public class TestState {
@Test
public void StateTest(){
Context context = new Context();
StartState openState = new OpenState();
startState.open(context);
startState.close(context);
CloseState stopState = new CloseState();
stopState.open(context);
stopState.close(context);
}
}
备忘录模式可以保存一个对象的某个状态,以便在适当的时候恢复对象状态。类似于游戏中的存档与读档。
作用:可以在不破坏程序封装的前提下,提前捕获并保存一个对象的内部状态,以便之后将对象恢复到已保存的状态。
优点:提供了一种可以恢复状态的机制,对用户较为友好,提高了用户操作时的容错率,并且无需关心保存细节。
缺点:会消耗更多资源。
示例:
public class Memento {
private String state;
public Memento(String state){
this.state = state;
}
public String getState(){
return state;
}
}
public class RunningState {
private String state;
public void setState(String state){
this.state = state;
}
public String getState(){
return state;
}
public Memento saveState(){
return new Memento(state);
}
public void readState(Memento Memento){
state = Memento.getState();
}
}
public class StateTaker {
private List mementoList = new ArrayList();
public void add(Memento state){
mementoList.add(state);
}
public Memento get(int index){
return mementoList.get(index);
}
}
测试:
public class TestMemento {
@Test
public void MementoTest(){
RunningState runningState = new RunningState();
StateTaker stateTaker = new StateTaker();
runningState.setState("Start");
runningState.setState("Block");
stateTaker.add(runningState.saveState());
runningState.setState("ReStart");
stateTaker.add(runningState.saveState());
runningState.setState("End");
System.out.println("当前状态:" + runningState.getState());
runningState.readState(stateTaker.get(0));
System.out.println("记录状态1:" + runningState.getState());
runningState.readState(stateTaker.get(1));
System.out.println("记录状态2:" + runningState.getState());
}
}