Muitos objetos com estado global e local
Pergunta
Eu estou procurando o melhor projeto para a seguinte situação.
Temos muitos objetos formam uma classe, por exemplo, um quadro de imagem. Agora cada uma das molduras pode exibir 3 tipos de imagem. 1) uma face 2) uma imagem 3) esvaziar
Isso é simples:
public enum PictureMode
{
Face,
Screen,
None
}
public class PictureFrame {
private PictureMode mode;
public PictureMode Mode
{
get { retrun mode; }
set { /* set currentPicture to the correct one */ }
}
private Image currentPicture;
private Image face;
private Image screen;
private Image empty;
public PictureFrame(Image face, Image screen) {
this.face = face;
this.screen = screen;
mode = PictureMode.None; // Maybe this is our default.
}
}
Podemos agora criar algumas pictureframes com retratos diferentes e facilmente alterar o modo para cada um.
Agora eu quero adicionar um setter global para todos os pictureframes. Em seguida, cada nova PictureFrame deve tomar a configuração global como um padrão. Ele pode depois ser ajustado para um meio diferente.
Aqui está a minha solução, mas eu quero discutir se existe um melhor.
Eu adicionei PictureFrame.Instances campo estático para a classe PictureFrame onde todos pictureframes são acessíveis. Agora eu posso iterar sobre todos os pictureframes para aplicar o novo modo global para todos os quadros.
Além disso, tenho um segundo campo estático PictureFrame.GlobalImageMode onde eu definir o modo global, se eu mudá-lo em todos os quadros e lê-lo no construtor do PictureFrame. O setter para o GlobalImageMode pode ser estático na classe PictureFrame também.
Solução
Apenas tiro selvagem aqui ...: Por que você não use sempre getter para o modo de quadro atual com uma condição em que:
class PictureFrame {
private PictureMode instanceMode;
private static PictureMode? globalMode;
private PictureMode CurrentMode {
get {
return globalMode ?? instanceMode;
}
}
}
Outras dicas
Se eu entendi a declaração do problema corretamente, penso que este é semelhante ao que você precisa:
public class Face extends Image { }
public class Screen extends Image { }
public class PictureFrame {
private Image picture = null;
public PictureFrame(Image newPicture) {
this.setPicture(newPicture);
}
public setPicture(Image newPicture) {
this.picture = newPicture;
}
}
public class PictureFactory {
private static Image defaultPicture = null;
public static void setDefaultPicture(Image newPicture) {
PictureFactory.defaultPicture = newPicture;
}
public static Image getDefaultPicture() {
return PictureFactory.defaultPicture;
}
public static PictureFrame getNewPictureFrame() {
return new PictureFrame(PictureFactory.defaultPicture);
}
}
public class PictureFrameManager {
private static PictureManager INSTANCE = new PictureManager();
private Vector<PictureFrame> frames = new Vector<PictureFrame>();
public static PictureFrameManager getInstance() {
return PictureManager.INSTANCE;
}
private PictureFrameManager() {}
private void addPictureFrame(PictureFrame frame) {
this.frames.add(frame);
}
private void setFramesToDefault() {
Image defaultPicture = PictureFactory.getDefaultPicture();
Enumeration<PictureFrame> iFrames = frames.elements();
while(iFrames.hasMoreElements()) {
iFrames.nextElement().setPicture(defaultPicture);
}
}
}
Você usá-lo via:
Face face = new Face();
//...do something to load the face object here
PictureFactory.setDefaultPicture(face);
PictureFrame frame = PictureFactory.getNewPictureFrame();
PictureFrameManager manager = PictureFrameManager.getInstance();
manager.addPictureFrame(frame);
Screen screen = new Screen();
//...do something to load the screen object here
PictureFactory.setDefaultPicture(screen);
manager.setFramesToDefault();
Como alternativa, se você não quiser estender imagem ou você quer ter múltiplos modos, você pode criar um objeto decorador para embrulhar a imagem e dizer o modo que é.