假设我有以下界面/具体类:
interface EmailFormatter
class CvEmailFormatter implements EmailFormatter
class RegistrationEmailFormatter implements EmailFormatter
class LostPasswordEmailFormatter implements EmailFormatter
然后我有一个自定义的“邮件程序”服务,该服务是从我的控制器操作中调用的,以便发送电子邮件。
根据发送的电子邮件类型,我有哪些选项可以将正确的EmailFormatter实施注入我的邮件服务?
答案 0 :(得分:1)
我会创建一个服务,在运行时选择正确的格式化程序,或者某种工厂,或者如果你的格式化程序有依赖关系,那么你可以从容器中注入格式化程序。像这样:
/*
* Copyright (C) 2010 Andrew Gainer
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Adapted from Android's CountDownTimer class
package com.cycleindex.multitimer;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
/**
* Schedule a countdown until a time in the future, with
* regular notifications on intervals along the way.
*
* The calls to {@link #onTick(long)} are synchronized to this object so that
* one call to {@link #onTick(long)} won't ever occur before the previous
* callback is complete. This is only relevant when the implementation of
* {@link #onTick(long)} takes an amount of time to execute that is significant
* compared to the countdown interval.
*/
public abstract class CountDownTimerWithPause {
/**
* Millis since boot when alarm should stop.
*/
private long mStopTimeInFuture;
/**
* Real time remaining until timer completes
*/
private long mMillisInFuture;
/**
* Total time on timer at start
*/
private final long mTotalCountdown;
/**
* The interval in millis that the user receives callbacks
*/
private final long mCountdownInterval;
/**
* The time remaining on the timer when it was paused, if it is currently paused; 0 otherwise.
*/
private long mPauseTimeRemaining;
/**
* True if timer was started running, false if not.
*/
private boolean mRunAtStart;
/**
* @param millisInFuture The number of millis in the future from the call
* to {@link #start} until the countdown is done and {@link #onFinish()}
* is called
* @param countDownInterval The interval in millis at which to execute
* {@link #onTick(millisUntilFinished)} callbacks
* @param runAtStart True if timer should start running, false if not
*/
public CountDownTimerWithPause(long millisOnTimer, long countDownInterval, boolean runAtStart) {
mMillisInFuture = millisOnTimer;
mTotalCountdown = mMillisInFuture;
mCountdownInterval = countDownInterval;
mRunAtStart = runAtStart;
}
/**
* Cancel the countdown and clears all remaining messages
*/
public final void cancel() {
mHandler.removeMessages(MSG);
}
/**
* Create the timer object.
*/
public synchronized final CountDownTimerWithPause create() {
if (mMillisInFuture <= 0) {
onFinish();
} else {
mPauseTimeRemaining = mMillisInFuture;
}
if (mRunAtStart) {
resume();
}
return this;
}
/**
* Pauses the counter.
*/
public void pause () {
if (isRunning()) {
mPauseTimeRemaining = timeLeft();
cancel();
}
}
/**
* Resumes the counter.
*/
public void resume () {
if (isPaused()) {
mMillisInFuture = mPauseTimeRemaining;
mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
mHandler.sendMessage(mHandler.obtainMessage(MSG));
mPauseTimeRemaining = 0;
}
}
/**
* Tests whether the timer is paused.
* @return true if the timer is currently paused, false otherwise.
*/
public boolean isPaused () {
return (mPauseTimeRemaining > 0);
}
/**
* Tests whether the timer is running. (Performs logical negation on {@link #isPaused()})
* @return true if the timer is currently running, false otherwise.
*/
public boolean isRunning() {
return (! isPaused());
}
/**
* Returns the number of milliseconds remaining until the timer is finished
* @return number of milliseconds remaining until the timer is finished
*/
public long timeLeft() {
long millisUntilFinished;
if (isPaused()) {
millisUntilFinished = mPauseTimeRemaining;
} else {
millisUntilFinished = mStopTimeInFuture - SystemClock.elapsedRealtime();
if (millisUntilFinished < 0) millisUntilFinished = 0;
}
return millisUntilFinished;
}
/**
* Returns the number of milliseconds in total that the timer was set to run
* @return number of milliseconds timer was set to run
*/
public long totalCountdown() {
return mTotalCountdown;
}
/**
* Returns the number of milliseconds that have elapsed on the timer.
* @return the number of milliseconds that have elapsed on the timer.
*/
public long timePassed() {
return mTotalCountdown - timeLeft();
}
/**
* Returns true if the timer has been started, false otherwise.
* @return true if the timer has been started, false otherwise.
*/
public boolean hasBeenStarted() {
return (mPauseTimeRemaining <= mMillisInFuture);
}
/**
* Callback fired on regular interval
* @param millisUntilFinished The amount of time until finished
*/
public abstract void onTick(long millisUntilFinished);
/**
* Callback fired when the time is up.
*/
public abstract void onFinish();
private static final int MSG = 1;
// handles counting down
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
synchronized (CountDownTimerWithPause.this) {
long millisLeft = timeLeft();
if (millisLeft <= 0) {
cancel();
onFinish();
} else if (millisLeft < mCountdownInterval) {
// no tick, just delay until done
sendMessageDelayed(obtainMessage(MSG), millisLeft);
} else {
long lastTickStart = SystemClock.elapsedRealtime();
onTick(millisLeft);
// take into account user's onTick taking time to execute
long delay = mCountdownInterval - (SystemClock.elapsedRealtime() - lastTickStart);
// special case: user's onTick took more than mCountdownInterval to
// complete, skip to next interval
while (delay < 0) delay += mCountdownInterval;
sendMessageDelayed(obtainMessage(MSG), delay);
}
}
}
};
}
或者,如果您必须在构建期间将格式化程序传递到邮件程序中,您还可以使用不同的别名创建多个不同的设置实例,然后根据需要将它们注入到服务和控制器中,如下所示:
class MailController extends AbstractController
{
private $mailer;
private $mailFormatterSelector;
public function __construct(...) { ... }
public function someAction()
{
// Do stuff ...
if (...some condition) {
$formatter = $this->mailFormatterSelector->getRegisterMailFormatter();
} else {
$formatter = $this->mailFormatterSelector->getLostPasswordEmailFormatter();
}
$mailer->sendEmail($formatter);
// Do more stuff ...
}
}
class MailFormatterSelector()
{
private $registrationFormatter;
public function __construct(EmailFormatter $registrationFormatter, ...)
{
$this->registrationFormatter = $registrationFormatter;
...
}
public function getRegisterMailFormatter(): EmailFormatter
{
return $this->registrationFormatter;
}
// ...
}
在您的控制器或操作中,您可以通过mailer1,mailer2,...(可能有更好的名字)传递。